С pcregrep
:
pcregrep -rMl '^C.*\nC' .
POSIXly:
find . -type f -exec awk '
FNR==1 {last=0; printed=0; next}
printed {next}
/^C/ {if (last) {print FILENAME; printed=1; nextfile} else last=1; next}
{last=0}' {} +
(хотя это означает полное чтение всех файлов с теми awk
реализациями, которые не поддерживают nextfile
).
С версиями GNU grep
до 2.5.4:
grep -rlP '^C.*\nC' .
кажется, что работает, но это случайно, и это не гарантировано, чтобы работать.
Прежде, чем это было исправлено в 2.6 (с помощью этого коммита ), GNU grep
упустила из виду, что используемая им функция поиска pcre будет соответствовать всему буферу, обрабатываемому в данный момент grep
, вызывая все виды неожиданного поведения. Например:
grep -P 'a\s*b'
будет соответствовать на файле, содержащем:
bla
bla
Это будет соответствовать:
printf '1\n2\n' | grep -P '1\n2'
Но это:
(printf '1\n'; sleep 1; printf '2\n') | grep -P '1\n2'
Или:
(yes | head -c 32766; printf '1\n2\n') > file; grep -P '1\n2' file
не будет (так как 1\n2\n
обрабатывается через два буфера grep
).
Это поведение в итоге было задокументировано, хотя:
15- Как я могу сопоставить между строк?
Стандартный grep не может этого сделать, так как он основан на строках. Поэтому простое использование класса символов '[: space:]' не соответствует символу новой строки, как вы ожидаете. Однако, если ваш grep скомпилирован с включенными шаблонами Perl, можно использовать модификатор Perl '(который заставляет'. 'Соответствовать символам новой строки):
printf 'foo\nbar\n' | grep -P '(?s)foo.*?bar'
После того, как это было исправлено в 2.6, документация не была изменена (я однажды сообщил об этом там ).
C
втором примере начинаются две строки .