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

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

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

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

13 ответов

Решение

Итак, я обнаружил pcregrep, который обозначает Perl-совместимые регулярные выражения GREP.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Он ищет тег заголовка в HTML-файле, даже если он занимает до 5 строк.

Вот пример неограниченного количества строк:

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

С серебряным искателем:

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

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

Этот ответ может быть полезен:

Требуется регулярное выражение (grep) для многострочного поиска

Для рекурсивного поиска вы можете использовать флаги -R (рекурсивный) и --include (шаблон GLOB). Увидеть:

Используйте синтаксис grep --exclude/- include, чтобы не просматривать определенные файлы

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

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

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

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

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

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

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

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

С помощью ex / vi опция редактора и globstar (синтаксис похож на awk а также sed):

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

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

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

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

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

Как ранее ответил Амит, вы можете использовать awk для поиска нескольких строк. Если вам нужно напечатать номер строки, используйте следующее:

      awk '/Start pattern/,/End pattern/ {print NR ":" $0}' filename

Я считаю, что следующее должно работать и имеет преимущество использования только расширенных регулярных выражений без необходимости установки дополнительного инструмента, такого какpcregrepесли у вас его еще нет или у вас нет-Pдоступна опция grep (например, macOS):

egrep -irzo “.*aaa(.*\s.*){1,}.*bbb.*" path_to_filenames

Предостережение: это имеет некоторые небольшие недостатки:

  • он найдет самый большой набор строк от первой до последней в каждом файле, если только...
  • есть несколько повторенийaaa[вещи]bbbшаблон в каждом файле.
Другие вопросы по тегам