Я в конечном счете решил это использование решения, подобного artyom's.
Шаг 1: Взорвите патч в большое количество отдельных патчей, один для каждого ломтя.
Я использовал этот сценарий, чтобы сделать это:
#!/usr/bin/python2
import sys
header = []
writing_header = False
patchnum = 0
patch = open(sys.argv[1], "r")
out = open("/dev/null", "w")
for line in patch.readlines():
if line.startswith("diff"):
header = []
writing_header = True
if line.startswith("@@"):
out.close()
out = open(str(patchnum) + ".diff", "w")
patchnum += 1
writing_header = False
out.writelines(header)
if writing_header:
header.append(line)
else:
out.write(line)
out.close()
Использование в качестве примера:
$ cd directory_containing_patch
$ mkdir foo
$ cd foo
$ explode.py ../huge_patch.diff
Это заполнит текущий каталог с файлами, названными 0.diff 1.diff и так далее.
Шаг 2: Примените каждый патч, уже отбросив применяемые патчи.
Я использовал этот сценарий, чтобы сделать это:
#!/bin/bash
if [[ $# -ne 1 || ! -d "${1}/" ]]; then
echo "Usage: $0 dirname"
exit 1
fi
find "$1" -name \*.diff | while read f; do
OUTPUT=$(patch -s -p1 -r- -i"$f")
if [ $? -eq 0 ]; then
rm "$f"
else
if echo "$OUTPUT" | grep -q "Reversed (or previously applied) patch detected!"; then
rm "$f"
fi
fi
done
Использование в качестве примера:
$ cd directory_containing_code
$ apply_patches.bash directory_containing_patch/foo
Это удалит любой из ранее сгенерированных патчей, которые применяются чисто или которые были уже применены. Любые патчи оставлены внутри foo
отклонения, которые должны быть вручную исследованы и объединены.
Если вы проверяете содержимое переменной окружения PATH
, а не ищете что-то в файле, то grep
является неверным инструментом. Проще (и быстрее, и, возможно, более читабельно) сделать это в оболочке.
В bash, ksh и zsh:
if [[ :$PATH: = *:/opt/gnome:* ]]; then
: # already there
else
PATH=$PATH:/opt/gnome
fi
Portably:
case :$PATH: in
*:/opt/gnome:*) :;; # already there
*) PATH=$PATH:/opt/gnome;;
esac
Обратите внимание на использование :$PATH:
вместо $PATH
; таким образом, компонент всегда окружен двоеточиями в строке поиска, даже если он находится в начале или в конце $PATH
.
Если вы ищете через строку файла, то вы можете использовать расширенный регеxp (т.е. требуя grep -E
) (^|:)/opt/gnome($|:)
на соответствие /opt/gnome
, но только если он находится либо в начале строки, либо после двоеточия, и только если он находится либо в конце строки, либо после двоеточия.
Если вы не средаете GREP
, вы можете использовать awk
и отделите записи на :
awk 'BEGIN {RS=":"} /^\/opt\/gnome$/'
-121------42397- Вы можете использовать расширенные регулярные выражения, просто используя grep -e
, вы должны соответствовать началу и конец пути, который вы пытаетесь найти, если вы хотите избежать ложных поставок.
соответствует экземпляру в начале:
$ TEST=/opt/gnome:/sbin:/usr/sbin:/var/opt/gnome
$ echo $TEST | grep -E "(:|^)/opt/gnome(:|$)"
/opt/gnome:/sbin:/usr/sbin:/var/opt/gnome
также соответствует экземпляру в середине:
$ TEST=/sbin:/usr/sbin:/opt/gnome:/var/opt/gnome
$ echo $TEST | grep -E "(:|^)/opt/gnome(:|$)"
/sbin:/usr/sbin:/opt/gnome:/var/opt/gnome
, избегая ложных срабатываний:
$ TEST="/home/bob/opt/gnome:/opt/gnome/somethingelse:/opt/gnome-beta"
$ echo $TEST | grep -E "(:|^)/opt/gnome(:|$)"
нет совпадений.
Компактный и элегантный. Проверено на Debian 7.
, чтобы выбрать / opt / gnome
, окруженные без слова символов (новые строки, :
, /
, и т. Д.). Попробуйте:
grep '\B/opt/gnome'
Вы можете сделать это надежно и без особых усилий в grep
. Вы можете воспользоваться широко доступными расширениями, среди которых уже предложены многие решения, но даже с базовым регексом это сделать легко, хотя на первый взгляд это может быть не интуитивно понятно.
С базовым регексом - и так с grep
- у вас всегда есть два надежных анкера - головка и хвост линии. Вы можете закрепить совпадение с обоими этими независимо от их расположения на линии , например:
grep '^\(ignore case, delimiter\)*match\(delimiter, ignore case\)*$'
grep
будет совпадать с заголовком линии столько же раз, сколько и подвыражения \(grouped\)
, сколько должно встретиться со следующим вашим разделителем, затем вашим явным совпадением, и с хвостом вашего совпадения с хвостом линии тем же самым способом. Если ваше явное совпадение не совпадает с explicit, то оно не будет выведено и ничего не будет выведено.
И вы можете сделать это, например:
grep '^\(.*:\)*/opt/gnome\(:.*\)*$'
Посмотрите сами:
grep '^\(.*:\)*/opt/gnome\(:.*\)*$
' <<\INPUT
/opt/gnome-beta
/opt/gnome
/home/bob/opt/gnome
:/opt/gnome:
/home/bob/opt/gnome:/opt/gnome:/opt/gnome-beta
/opt-gnome-beta
/opt/gnomenot::::/opt/gnome
INPUT
/opt/gnome
:/opt/gnome:
/home/bob/opt/gnome:/opt/gnome:/opt/gnome-beta
/opt/gnomenot::::/opt/gnome
Если вы не женаты на grep
, вы можете использовать awk
и разделить записи на :
awk 'BEGIN {RS=":"} /^\/opt\/gnome$/'
вы заметили крайний случай... вы можете избежать его, принудив появление a : в начале строки :
echo ":$PATH" | grep ":/opt/gnome"
или, если путь точный, добавить также один в конце, чтобы убедиться, что он ограничен :
echo ":${PATH}:" | grep ":/opt/gnome:"
Можно также использовать
эхо "$PATH". | tr ':' '\n' | grep -x "/opt/gnome"
, который разделяет переменную пути на отдельные строки (по одной на путь), так что grep -x
может искать точный результат.
Недостатком этого, конечно же, является необходимость дополнительного процесса для tr
. И он не будет работать, когда имя папки в PATH
содержит символы новой строки.
Я не знаю, это достаточно для ответа, но
grep -w "/opt/gnome"
удовлетворит вашу потребность.
echo '/sbin:/usr/sbin:/opt/gnome:/var/opt/gnome' | grep -w "/opt/gnome" -o
/opt/gnome
echo '/opt/gnome:/sbin:/usr/sbin:/var/opt/gnome' | grep -w "/opt/gnome" -o
/opt/gnome
Но
echo '/opt/gnome:/sbin:/usr/sbin:/var/opt/gnome' | grep "/opt/gnome" -o
/opt/gnome
/opt/gnome