У меня есть два файла, file1
и file2
.
Пример содержания file1
:
A B
C D
E F
G H
и содержание file2
как:
A B
few other lines
E F
few more other lines
A B
C D
E F
G H
few more other lines
G H
Поэтому я хочу искать весь блок file1
контента file2
только. Это означает, что вывод должен содержать только эти строки:
A B
C D
E F
G H
обратите внимание, что: - только строки, которые собираются вместе, должны быть частью вывода.
file1
и ничего больше, просто используйтеcat file1
.Ответы:
grep
довольно глупо, когда дело доходит до многострочных шаблонов, но перевод всех символов новой строки\n
как шаблона, так и текста для поиска в NUL-символы\0
перед их сравнением исправляет это. Перевод\0
в выводе обратно,\n
очевидно, также необходим.Вот ваша команда, предполагая, что она
file1
содержит шаблон, в котором вы хотите искатьfile2
:Пример вывода для заданных вами файлов:
Объяснение:
<(tr '\n' '\0' < file1)
создает FIFO / именованный канал / временный файлоподобный объект, равныйfile1
, но со всеми символами новой строки, переведенными в символы NUL.<(tr '\n' '\0' < file2)
делает то же самое, но дляfile2
.grep -f PATTERN_FILE INPUT_FILE
ищет шаблон (ы) изPATTERN_FILE
inINPUT_FILE
.-a
Флагgrep
позволяет согласование бинарных файлов. Это необходимо, потому что в противном случае он будет пропускать файлы, которые содержат непечатные символы, такие как\0
.-o
Флагgrep
делает его печать только последовательность согласования, а не вся линия , где она была найдена.| tr '\0' '\n'
переводит все NUL-символы из выходных данных команды слева обратно в символы новой строки.источник
Следующее неуклюже, но работает с GNU
awk
:источник
Просто для удовольствия в чистом виде
источник
Вот немного более элегантный
grep
+perl
:Тем не менее, есть один большой улов. Если есть завершающий символ новой строка в
file1
, картина не будет правильной, другими словаA B\nC D\nE F\nG H\n\n
.(Отдельное спасибо @terdon за предоставленную часть Perl)
Как отмечалось в costas, можно использовать
perl -0pe 's/\n(\n+$)?/\\n/g'
вместо другойperl
команды, чтобы избежать завершающего символа новой строки вfile1.txt
источник
perl -0pe 's/\n(\n+$)?/\\n/g'
. Без-0
вg
регулярных выражениях модификатора является дополнительным.Я не очень уверен, что вы хотите, чтобы вывод был, но это легко сделать с языками, которые не являются исключительно ориентированными на строки (особенно если оба файла могут быть прочитаны в память). Вот скрипт Python, который скажет вам, сколько совпадений.
Вы хотите напечатать
file1
столько раз, сколько это соответствует? Замените последнюю строку на это:Вы можете упаковать все в вызов командной строки или псевдоним, если вы действительно хотите:
источник
Результатом будут все файлы с точным совпадением текста
источник
Вот еще один подход, использующий python (протестирован с
python3 3.5.2
, без нареканийpylint3 1.5.6
):Обработка аргументов командной строки через,
sys.argv
по общему признанию, упрощена. Вы можете сделать много других вещей с возвращаемым значениемfinder
двухmemoryview
передаваемых вами объектов, кроме того, чтобы передать егоtuple
. КаждыйSRE_Match
элемент, возвращаемый итератором, возвращаемым функцией,finder
имеет множество методов, выборка которых суммируется вprint
выходных данных (span
например, сообщает диапазон байтов каждого соответствия).источник