Regex (grep) для многострочного поиска [дубликат]
Возможные Дубликаты:
как я могу искать многострочный шаблон в файл ? Использовать pcregrep
Я grep
найти *.файл sql, который имеет слово select
после слова customerName
после слова from
. Эта инструкция select может охватывать множество строк и содержать вкладки и новые строки.
Я пробовал несколько вариантов следующего:
$ grep -liIr --include="*.sql" --exclude-dir=".svn*" --regexp="select[a-zA-Z0-
9+nr]*customerName[a-zA-Z0-9+nr]*from"
этот, однако, просто бежит вечно. Кто-нибудь может помочь мне с правильным синтаксисом, пожалуйста?
3 ответов
без необходимости установки grep вариант pcregrep, вы можете сделать многострочный поиск с grep.
$ grep -Pzo "(?s)^(\s*)\N*main.*?{.*?^}" *.c
объяснение:
-P
активировать perl-regexp для grep (мощное расширение регулярных расширений)
-z
подавления новой строки в конце строки, subtituting это для нуль-символа. То есть grep знает, где конец строки, но видит вход как одну большую строку.
-o
печать только соответствия. Потому что мы используем -z
, весь файл похож на одну большую строку, поэтому, если есть совпадение, весь файл будет напечатан; таким образом, он этого не сделает.
в регулярное выражение:
(?s)
активировать PCRE_DOTALL
, что означает .
находит любой символ или строку
\N
найти что-нибудь, кроме newline, даже с PCRE_DOTALL
активирован
.*?
найти .
в режиме из жадного в нежадный, то есть как можно быстрее останавливается.
^
найти начало линия
backreference к первой группе (
\s*
) это попытка найти тот же отступ метода
как вы можете себе представить, этот поиск выводит основной метод в C (*.c
файл) источник.
Я не очень хорошо в grep. Но ваша проблема может быть решена с помощью на awk.
Просто смотри!--7-->
приведенный выше код будет результатом первого вхождения awk '/select/,/from/' *.sql
select
до первой последовательности from
. Теперь вам нужно проверить, имеют ли возвращаемые операторы customername
или нет. Для этого вы можете передать результаты. И может использовать awk или grep снова.
ваша основная проблема в том, что grep
работает по одной строке за раз-поэтому он не может найти инструкцию SELECT, распределенную по строкам.
ваша вторая проблема заключается в том, что регулярное выражение, которое вы используете, не имеет дело со сложностью того, что может появиться между SELECT и FROM - в частности, оно опускает запятые, полные остановки (периоды) и пробелы, но также кавычки и все, что может быть внутри строки с кавычками.
Я, вероятно, пойду с решением на основе Perl, прочитав Perl "абзацы" за раз и применение регулярного выражения к этому. Недостатком является необходимость иметь дело с рекурсивным поиском - для этого, конечно, есть модули, включая основной модуль File:: Find.
в общих чертах, для одного файла:
$/ = "\n\n"; # Paragraphs
while (<>)
{
if ($_ =~ m/SELECT.*customerName.*FROM/mi)
{
printf file name
go to next file
}
}
это должно быть обернуто в sub, который затем вызывается методами File:: Find.