Как искать многострочный шаблон в файле?

Мне нужно было найти все файлы, содержащие определенный шаблон строки. Первое решение, которое приходит на ум, это использовать find pipeed с xargs grep:

find . -iname '*.py' | xargs grep -e 'YOUR_PATTERN'

Но если мне нужно найти шаблоны, которые охватывают более одной строки, я застрял, потому что ванильный grep не может найти многострочные шаблоны.

Ответ 1

Итак, я обнаружил pcregrep, что означает Perl Compatible Regular Expressions GREP.

Например, вам нужно найти файлы, где переменная "_name" сразу же следует переменной "_description":

find . -iname '*.py' | xargs pcregrep -M '_name.*\n.*_description'

Совет. Вам нужно включить символ разрыва строки в свой шаблон. В зависимости от вашей платформы это могут быть "\n", "r", "\ r\n",...

Ответ 2

Почему бы вам не пойти на awk:

awk '/Start pattern/,/End pattern/' filename

Ответ 3

Вот пример использования GNU grep:

grep -Pzo '_name.*\n.*_description'

-z/--null-data Обрабатывать входные и выходные данные как последовательности строк.

Смотрите также здесь

Ответ 4

grep -P также использует libpcre, но гораздо более широко установлен. Чтобы найти полный раздел title html-документа, даже если он охватывает несколько строк, вы можете использовать это:

grep -P '(?s)<title>.*</title>' example.html

Поскольку проект PCRE реализует стандарт perl, используйте документацию perl для справки:

Ответ 5

Вот более полезный пример:

pcregrep -Mi "<title>(.*\n){0,5}</title>" afile.html

Он ищет тег заголовка в html файле, даже если он охватывает до 5 строк.

Вот пример неограниченных строк:

pcregrep -Mi "(?s)<title>.*</title>" example.html 

Ответ 6

С помощью серебряного искателя:

ag 'abc.*(\n|.)*efg'

Оптимизация скорости искателя серебра могла бы сиять здесь.

Ответ 7

Вы можете использовать альтернативный просеиватель grep здесь (отказ от ответственности: я автор).

Он поддерживает многострочное сопоставление и ограничение поиска по конкретным типам файлов из коробки:

sift -m --files '*.py' 'YOUR_PATTERN'

(найдите все *.py файлы для указанного многострочного шаблона регулярного выражения)

Он доступен для всех основных операционных систем. Взгляните на страницу образцов, чтобы узнать, как ее можно использовать для извлечения многострочных значений из файла XML.

Ответ 9

perl -ne 'print if (/begin pattern/../end pattern/)' filename

Ответ 10

@Marcin: awk пример не-жадный:

awk '{if ($0 ~ /Start pattern/) {triggered=1;}if (triggered) {print; if ($0 ~ /End pattern/) { exit;}}}' filename

Ответ 11

Использование ex/vi редактора и опции globstar (синтаксис, похожий на awk и sed):

ex +"/string1/,/string3/p" -R -scq! file.txt

где aaa - ваша отправная точка, а bbb - ваш окончательный текст.

Чтобы искать рекурсивно, попробуйте:

ex +"/aaa/,/bbb/p" -scq! **/*.py

Примечание. Чтобы включить ** синтаксис, запустите shopt -s globstar (Bash 4 или zsh).