Je voudrais obtenir la correspondance multi-motifs avec AND entre les motifs, cest-à-dire équivalent à exécuter plusieurs greps dans une séquence:

grep pattern1 | grep pattern2 | ... 

Alors comment le convertir en quelque chose comme?

grep pattern1 & pattern2 & pattern3 

Je voudrais utiliser un seul grep parce que je construis des arguments de manière dynamique, donc tout doit tenir dans une chaîne. Utiliser le filtre est une fonctionnalité système, pas grep, donc ce nest pas un argument pour cela.


Ne confondez pas cette question avec:

grep "pattern1\|pattern2\|..." 

Il sagit dune correspondance à plusieurs modèles OU .

Commentaires

Réponse

agrep peut le faire avec cette syntaxe:

agrep "pattern1;pattern2" 

Avec GNU grep, une fois construit w Avec le support PCRE, vous pouvez faire:

grep -P "^(?=.*pattern1)(?=.*pattern2)" 

Avec ast grep :

grep -X ".*pattern1.*&.*pattern2.*" 

(ajout de .* en tant que <x>&<y> correspond aux chaînes qui correspondent à la fois à <x> et <y> exactement , a&b ne correspondrait jamais car il » ny a pas de chaîne de ce type qui peut être à la fois a et b en même temps).

Si les motifs ne se chevauchent pas, vous pouvez également faire:

grep -e "pattern1.*pattern2" -e "pattern2.*pattern1" 

Le meilleur moyen portable est probablement avec awk comme déjà mentionné:

awk "/pattern1/ && /pattern2/" 

Avec sed:

sed -e "/pattern1/!d" -e "/pattern2/!d" 

Veuillez noter que tous ceux-ci auront une syntaxe dexpression régulière différente.

Commentaires

  • La syntaxe agrep ne fonctionne pas pour moi … dans quelle version a-t-il été introduit?
  • @Raman 2.04 de 1992 lavait déjà. Je ‘ n’a aucune raison de croire qu’il n’y était pas ‘ depuis le début. Des versions plus récentes (après 1992) de agrep peuvent être trouvées incluses avec glimpse / webglimpse . Vous avez peut-être une implémentation différente. Jai eu une erreur pour la version ast-grep cependant, loption pour regexps augmentés est -X, pas -A.
  • @St é phaneChazelas Merci, jai agrep 0.8.0 sur Fedora 23. Cela semble être un agrep différent de celui auquel vous faites référence.
  • @Raman, le vôtre ressemble à TRE agrep .
  • @Techiee, ou simplement awk '/p1/ && /p2/ {n++}; END {print 0+n}'

Réponse

Vous navez pas spécifié la version de grep, cest important. Certains moteurs dexpressions rationnelles autorisent plusieurs correspondances groupées par AND en utilisant « & « mais ce nest pas une fonctionnalité standard et non portable. Mais, au moins GNU grep ne prend pas en charge cela.

OTOH vous pouvez simplement remplacer grep par sed, awk, perl, etc. (classés par ordre croissant de poids). Avec awk, la commande ressemblerait à

 awk "/regexp1/ && /regexp2/ && /regexp3/ { print; }" 

et elle peut être construite pour être spécifiée en ligne de commande de manière simple.

Commentaires

  • Souvenez-vous simplement que awk utilise des ERE ‘ s, par exemple léquivalent de grep -E, par opposition aux BRE ‘ s utilisés par grep. Les expressions rationnelles
  • awk ‘ sont appelées ERE, mais en fait elles ‘ est un peu idiosyncratique. Voici probablement plus de détails que quiconque ne souhaite: wiki.alpinelinux.org/wiki/Regex
  • Merci, grep 2.7.3 ( openSUSE). Je vous ai voté pour, mais je vais garder la question ouverte pendant un certain temps, peut-être quil y a une astuce pour grep (pas que je naime pas awk – simplement en savoir plus, cest mieux).
  • Laction par défaut est dimprimer la ligne correspondante de sorte que la partie { print; } nest ‘ pas vraiment nécessaire ou utile ici.

Réponse

Si patterns contient un motif par ligne, vous pouvez faire quelque chose comme ceci:

 awk "NR==FNR{a[$0];next}{for(i in a)if($0!~i)next}1" patterns -  

Ou cela correspond à des sous-chaînes au lieu de regular expressions:

 awk "NR==FNR{a[$0];next}{for(i in a)if(!index($0,i))next}1" patterns -  

Pour imprimer tout au lieu de pas de lignes de lentrée dans le si patterns est vide, remplacez NR==FNR par FILENAME==ARGV[1], ou par ARGIND==1 in gawk.

Ces fonctions impriment les lignes de STDIN qui contiennent chaque chaîne spécifiée comme argument comme sous-chaîne. ga signifie grep all et gai ignore la casse.

 ga(){ awk "FILENAME==ARGV[1]{a[$0];next}{for(i in a)if(!index($0,i))next}1" <(printf %s\\n "[email protected]") -; } gai(){ awk "FILENAME==ARGV[1]{a[tolower($0)];next}{for(i in a)if(!index(tolower($0),i))next}1" <(printf %s\\n "[email protected]") -; }  

Commentaires

  • réponse claire qui aborde plusieurs cas dusages et fonctionne (vérifiée sur macos)

Réponse

grep pattern1 | grep pattern2 | ...

Je voudrais utiliser un seul grep car je construis des arguments dynamiquement , donc tout doit tenir dans une chaîne

Il est en fait possible de construire le pipeline dynamiquement (sans recourir à eval):

 # Executes: grep "$1" | grep "$2" | grep "$3" | ... function chained-grep { local pattern="$1" if [[ -z "$pattern" ]]; then cat return fi shift grep -- "$pattern" | chained-grep "[email protected]" } cat something | chained-grep all patterns must match order but matter dont  

Ce nest probablement pas une solution très efficace.

Commentaires

  • Utilisez soit chained-grep() soit function chained-grep mais pas function chained-grep(): unix.stackexchange.com/questions/73750/…
  • Pouvez-vous décrire lastuce? Pouvez-vous lajouter à la réponse ( sans  » Edit: « ,  » Mettre à jour: « , ou similaire) en le modifier ?
  • Reformulé la réponse pour rendre le truc plus clair (cest-à-dire: construire dynamiquement un pipeline shell)

Réponse

git grep

Voici la syntaxe utilisant git grep combinaison de plusieurs modèles à laide dexpressions booléennes :

git grep --no-index -e pattern1 --and -e pattern2 --and -e pattern3 

La commande ci-dessus imprimera les lignes correspondant à tous les modèles à la fois.

--no-index Rechercher des fichiers dans le répertoire courant qui nest pas géré par Git.

Cochez man git-grep pour obtenir de laide.

Voir aussi:

Pour lopération OR , voir:

Commentaires

  • Superbe réponse. Merci.

Réponse

Voici mon avis, et cela fonctionne pour les mots sur plusieurs lignes:

Utilisez find . -type f suivi dautant de
-exec grep -q "first_word" {} \;
et le dernier mot-clé avec
-exec grep -l "nth_word" {} \;

-q quiet / silent
-l afficher les fichiers avec des correspondances

La liste suivante renvoie la liste des noms de fichiers contenant les mots « lapin » et « trou »:
find . -type f -exec grep -q "rabbit" {} \; -exec grep -l "hole" {} \;

Commentaires

  • Si vous regardez attentivement, vous apprendrez peut-être que ce nest pas la fonctionnalité que la question demande.

Réponse

ripgrep

Voici lexemple utilisant rg :

rg -N "(?P<p1>.*pattern1.*)(?P<p2>.*pattern2.*)(?P<p3>.*pattern3.*)" file.txt 

Cest lun des outils de grepping les plus rapides, car il est construit au-dessus de iv id = GH-875 .

Réponse

Pour trouver tous les mots (ou modèles), vous pouvez exécuter grep dans une boucle for. Le principal avantage ici est de rechercher dans une liste dexpressions régulières .

Un vrai exemple:

# File "search_all_regex_and_error_if_missing.sh" find_list="\ ^a+$ \ ^b+$ \ ^h+$ \ ^d+$ \ " for item in $find_list; do if grep -E "$item" file_to_search_within.txt then echo "$item found in file." else echo "Error: $item not found in file. Exiting!" exit 1 fi done 

Maintenant, exécutons-le sur ce fichier:

hhhhhhhhhh aaaaaaa bbbbbbbbb ababbabaabbaaa ccccccc dsfsdf bbbb cccdd aa caa 
$ ./search_all_regex_and_error_if_missing.sh aaaaaaa aa ^a+$ found in file. bbbbbbbbb bbbb ^b+$ found in file. hhhhhhhhhh ^h+$ found in file. Error: ^d+$ not found in file. Exiting! 

Commentaires

  • Votre logique est défectueuse – Jai demandé ALL, votre code fonctionne comme OR opérateur, pas AND. Et btw. Pour cela (OR) est une solution beaucoup plus simple donnée directement dans la question.
  • @greenoldman La logique est simple: la boucle for sur TOUS les mots / motifs dans la liste, et sil est trouvé dans le fichier – limprimera. Donc, supprimez simplement le else si vous navez ‘ pas besoin daction si le mot na pas été trouvé.
  • Je comprends votre logique ainsi que ma question – je vous posais une question sur lopérateur AND, ce qui signifie que le fichier nest quun résultat positif sil correspond au modèle A et au modèle B et motif C et … AND Dans votre cas, le fichier est positif sil est tches le motif A ou le motif B ou … Voyez-vous la différence maintenant?
  • @greenoldman ne sais pas pourquoi vous pensez que cette boucle ne vérifie pas la condition AND pour tous les motifs? Jai donc ‘ édité ma réponse avec un exemple réel: il recherchera dans le fichier tous les regex de la liste, et sur le premier qui manque, il se terminera avec une erreur.
  • Vous lavez juste devant vos yeux, vous avez une correspondance positive juste après lexécution de la première correspondance. Vous devriez avoir  » collecter  » tous les résultats et calculer AND dessus. Ensuite, vous devriez réécrire le script pour quil sexécute sur plusieurs fichiers – alors peut-être que vous vous rendez compte que la question a déjà reçu une réponse et que votre tentative napporte rien à la table, désolé.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *