Как мне найти многострочный шаблон в файле?
Мне нужно было найти все файлы, которые содержали определенный шаблон строки. Первое решение, которое приходит на ум, - это поиск по каналу с помощью 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
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
шаблон в каждом файле.