Avec pcregrep
:
pcregrep -rMl '^C.*\nC' .
POSIX:
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}' {} +
(bien que cela signifie lire tous les fichiers entièrement avec les awk
implémentations qui ne prennent pas en charge nextfile
).
Avec les versions de GNU grep
jusqu'à 2.5.4:
grep -rlP '^C.*\nC' .
semble fonctionner, mais c'est par accident et il n'est pas garanti de fonctionner.
Avant qu'il ne soit corrigé en 2.6 (par ce commit ), GNU grep
avait ignoré que la fonction de recherche pcre qu'il utilisait correspondrait à tout le tampon actuellement traité par grep
, provoquant toutes sortes de comportements surprenants. Par exemple:
grep -P 'a\s*b'
correspondrait à un fichier contenant:
bla
bla
Cela correspondrait à:
printf '1\n2\n' | grep -P '1\n2'
Mais ça:
(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
ne le ferait pas (comme l' 1\n2\n
est dans deux tampons traités par grep
).
Ce comportement a finalement été documenté:
15- Comment puis-je faire correspondre les lignes?
Le grep standard ne peut pas faire cela, car il est fondamentalement basé sur les lignes. Par conséquent, le simple fait d'utiliser la classe de caractères '[: space:]' ne correspond pas aux sauts de ligne comme vous vous en doutez. Cependant, si votre grep est compilé avec des modèles Perl activés, le modificateur Perl (qui fait correspondre les sauts de ligne ".") Peut être utilisé:
printf 'foo\nbar\n' | grep -P '(?s)foo.*?bar'
Après avoir été corrigé en 2.6, la documentation n'a pas été modifiée (je l'ai signalé une fois là- bas ).
C
dans votre deuxième exemple.