Grep для шаблона в запуске или середина строки

Я в конечном счете решил это использование решения, подобного 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 отклонения, которые должны быть вручную исследованы и объединены.

9
12.11.2014, 16:03
8 ответов

Если вы проверяете содержимое переменной окружения 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, но только если он находится либо в начале строки, либо после двоеточия, и только если он находится либо в конце строки, либо после двоеточия.

10
27.01.2020, 20:03

Если вы не средаете 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.

8
27.01.2020, 20:03

, чтобы выбрать / opt / gnome , окруженные без слова символов (новые строки, : , / , и т. Д.). Попробуйте:

grep '\B/opt/gnome'
0
27.01.2020, 20:03

Вы можете сделать это надежно и без особых усилий в 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

OUTPUT

/opt/gnome
:/opt/gnome:
/home/bob/opt/gnome:/opt/gnome:/opt/gnome-beta
/opt/gnomenot::::/opt/gnome
0
27.01.2020, 20:03

Если вы не женаты на grep, вы можете использовать awk и разделить записи на :

awk 'BEGIN {RS=":"} /^\/opt\/gnome$/'
7
27.01.2020, 20:03

вы заметили крайний случай... вы можете избежать его, принудив появление a : в начале строки :

 echo ":$PATH" | grep ":/opt/gnome"

или, если путь точный, добавить также один в конце, чтобы убедиться, что он ограничен :

 echo ":${PATH}:" | grep ":/opt/gnome:"
0
27.01.2020, 20:03

Можно также использовать

эхо "$PATH". | tr ':' '\n' | grep -x "/opt/gnome"

, который разделяет переменную пути на отдельные строки (по одной на путь), так что grep -x может искать точный результат. Недостатком этого, конечно же, является необходимость дополнительного процесса для tr. И он не будет работать, когда имя папки в PATH содержит символы новой строки.

5
27.01.2020, 20:03

Я не знаю, это достаточно для ответа, но

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
2
27.01.2020, 20:03

Теги

Похожие вопросы