И обязательное 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$//'
Объяснение, как указано выше, но с использованием новых строк в качестве разделителей вместо добавления #
.
Из описание POSIX grep :
По умолчанию, строка ввода должна быть выбрана, если какой-либо шаблон [...] соответствует любой части строки, за исключением завершающей
.
Нет, это не означает, что шаблоны объединяются вместе.
Это означает, что вы можете указать несколько шаблонов, при этом второй и последующие шаблоны не будут интерпретироваться как имена файлов.
Рассмотрим следующее:
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
Чтобы прояснить существующие комментарии и ответить :нет, это не работает так, как описано в ОП.
На самом деле:
grep -e foo -e bar -e baz myfile
выводит строки, содержащие либо foo
, либо bar
, либоbaz
.
grep foo myfile | grep bar | grep baz
выводит строки, содержащиеfoo
иbar
и baz
(, не обязательно в этом порядке ).