Что означает «указать несколько шаблонов поиска» с помощью «-e» в grep?

И обязательное sed решение:

sed '1s/^/#/;x;G;\_#\([^#]*\)#.*\n\1/_s/\n.*//;s/\n\(.*\)/\1#/;h;$! d;x;s/^#//;s/#$//;y/#/\n/'

Сценарий собирает пути в резервном пространстве. Для каждой новой строки пространство удержания добавляется к пространству шаблона, чтобы проверить, не произошло ли оно уже.

Это решение предполагает, что символ # не используется в файле. В противном случае используйте другой символ или, если вы используете GNU sed, используйте короткую версию внизу сообщения.

Подробное объяснение:

1s/^/#/

Для переносимости символ # используется для разделения путей в пространстве хранения. Для первой строки нам нужно начать с начального #

x;G

By exchanging the spaces and appending the hold space, we have the list of already occured buffers first, then the new path.

\_#\([^#]*\)#.*\n\1/_s/\n.*//

Если адрес \_..._ совпадает, новый путь является подпутью более раннего пути, поэтому удалите его.

s/\n\(.*\)/\1#/

В нашем пространстве все еще есть новая строка, поэтому путь новый, и мы добавляем его в список.

h;$! d

Сохраните новый список в резервной области и начните заново, если это не последняя строка.

x;s/^#//;s/#$//;y/#/\n/

В последней строке удалите # в начале и в конце и замените другие # символами новой строки.

Альтернатива для GNU sed

Это можно сделать более компактно с расширениями GNU на sed, если вы не возражаете, если порядок будет изменен:

sed 'G;\_^\([^\n]*\)/.*\n\1\n_s/[^\n]*\n//;h;$! d;x;s/^\n//;s/\n$//'

Объяснение, как указано выше, но с использованием новых строк в качестве разделителей вместо добавления #.

0
16.02.2017, 07:08
3 ответа

Из описание POSIX grep :

По умолчанию, строка ввода должна быть выбрана, если какой-либо шаблон [...] соответствует любой части строки, за исключением завершающей .

1
28.01.2020, 02:15

Нет, это не означает, что шаблоны объединяются вместе.

Это означает, что вы можете указать несколько шаблонов, при этом второй и последующие шаблоны не будут интерпретироваться как имена файлов.

Рассмотрим следующее:

grep pattern1 file1

Достаточно просто. Теперь подумайте:

grep pattern1 file1 file2

И:

# This doesn't work
grep pattern1 pattern2 file1 file2
# But this does.  There's no difference that's obvious to a computer.
grep pattern1 file1 file2 file3

Видите ли вы проблему?

Но с -eвы можете сделать:

grep -e pattern1 -e pattern2 file1 file2
2
28.01.2020, 02:15

Чтобы прояснить существующие комментарии и ответить :нет, это не работает так, как описано в ОП.

На самом деле:

grep -e foo -e bar -e baz myfile

выводит строки, содержащие либо foo, либо bar, либоbaz.

grep foo myfile | grep bar | grep baz

выводит строки, содержащиеfooиbarи baz(, не обязательно в этом порядке ).

3
28.01.2020, 02:15

Теги

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