com 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}' {} +
(embora isso signifique ler todos os arquivos totalmente com as implementações awk
que não suportam nextfile
).
Com versões do GNU grep
até 2.5.4:
grep -rlP '^C.*\nC' .
aparece para funcionar, mas é por acidente e não é garantido que funcione.
Antes de ser corrigido em 2.6 (por este commit ), O GNU grep
ignorou que a função de pesquisa do pcre que estava usando corresponderia a todo o buffer atualmente processado por grep
, causando todo tipo de comportamento surpreendente. Por exemplo:
grep -P 'a\s*b'
corresponderia em um arquivo contendo:
bla
bla
Isso corresponderia:
printf '1\n2\n' | grep -P '1\n2'
Mas isso:
(printf '1\n'; sleep 1; printf '2\n') | grep -P '1\n2'
Ou:
(yes | head -c 32766; printf '1\n2\n') > file; grep -P '1\n2' file
não (como o 1\n2\n
está em dois buffers processados por grep
).
Esse comportamento acabou sendo documentado:
15- How can I match across lines?
Standard grep cannot do this, as it is fundamentally line-based. Therefore, merely using the '[:space:]' character class does not match newlines in the way you might expect. However, if your grep is compiled with Perl patterns enabled, the Perl 's' modifier (which makes '.' match newlines) can be used:
printf 'foo\nbar\n' | grep -P '(?s)foo.*?bar'
Depois que foi corrigido em 2.6, a documentação não foi alterada (uma vez eu relatei que lá ).