Supposons que je veuille rechercher dans un arbre entier tous les fichiers CPP où "Foo" se produit. Je pourrais faire:
find . -name "*.cpp" | xargs grep "Foo"
Supposons maintenant que je souhaite lister uniquement les cas où une autre chaîne, par exemple "Bar", n'apparaît pas dans les 3 lignes du résultat précédent.
Donc, étant donné deux fichiers:
a.cpp
1 Foo
2 qwerty
3 qwerty
b.cpp
1 Foo
2 Bar
3 qwerty
Je voudrais construire une recherche simple où "Foo" de a.cpp se trouve, mais "Foo" de b.cpp ne l'est pas.
Existe-t-il un moyen d'accomplir cela d'une manière assez simple?
Réponses:
Avec
pcregrep
:La clé est dans l'
-M
option qui est uniquepcregrep
et utilisée pour faire correspondre plusieurs lignes (pcregrep
extrait plus de données du fichier d'entrée si nécessaire lors de la marche du RE l'exige).(?!...)
est l'opérateur RE à anticipation négative perl / PCRE.Foo(?!...)
correspondFoo
tant...
qu'il ne correspond pas à ce qui suit....
étant(?:.*\n){0,2}.*Bar
(.
ne correspondant pas à un caractère de nouvelle ligne), c'est-à-dire de 0 à 2 lignes suivies d'une ligne contenantBar
.la source
pcregrep
? Je n'en ai jamais entendu parler auparavant.(?!...)
négativeperl
.Peu importe, utilisez simplement
pcregrep
comme suggéré par @StephaneChazelas.Cela devrait fonctionner:
L'idée est d'utiliser le
-A
commutateur de grep pour sortir les lignes correspondantes et les N lignes suivantes. Vous passez ensuite le résultat à travers ungrep Bar
et si cela ne correspond pas (exit> 0), alors vous faites écho au nom du fichier.Si vous savez que vous avez des noms de fichiers raisonnables (pas d'espaces, de nouvelles lignes ou d'autres caractères étranges), vous pouvez simplifier pour:
Par exemple:
Notez que
c.cpp
est retourné malgré contenantBar
car la ligne avecBar
est plus de 3 lignes aprèsFoo
. Vous pouvez contrôler le nombre de lignes que vous souhaitez rechercher en modifiant la valeur passée à-A
:Voici un plus court (en supposant que vous utilisez
bash
):IMPORTANT
Comme Stephane Chazelas l'a souligné dans les commentaires, les solutions ci-dessus imprimeront également des fichiers qui ne contiennent pas
Foo
du tout. Celui-ci évite que:la source
Foo
. Vous avez des guillemets manquants.Foo
et j'ai corrigé cela, mais je ne vois pas votre point sur plusieurs instances deFoo
. Il devrait les traiter correctement.Non testé, je suis sur mon téléphone:
quelque chose comme ca.
la source