Cette question a déjà des réponses ici :

Commentaires

  • Que voulez-vous dire par " la partie entière de chaque chaîne "? Vous ' ne voulez pas que la ligne entière soit imprimée?
  • Pourriez-vous confirmer que vous voulez que les fichiers correspondants contiennent les deux " foo " et " 321 " mais pas seulement " foo " ou simplement " 321 "?
  • Jaime la façon dont ' s 321 au lieu de bar: – D

Réponse

GNU grep

Devrait être un peu plus rapide car le second grep peut opérer sur une liste de fichiers.

grep -lZ "foo" * | xargs -0 grep -l "321" 

POSIX grep avec find

find est plus utile si vous souhaitez rechercher des répertoires récursifs (dans ce cas, perdez -mindepth et -maxdepth options.

find . -mindepth 1 -maxdepth 1 -type f -exec grep -q "foo" {} \; -exec grep -l "321" {} + 

Commentaires

  • -r a bien fonctionné sur le premier grep pour rendre cette solution GNU récursive pour moi, au lieu dutiliser la ligne POSIX avec tous ces exec s

Answer

Vous pouvez le faire avec un court script:

for FILE in * do grep -q foo $FILE && grep -q 321 $FILE && echo $FILE done 

Vous pouvez également le faire sur une seule ligne:

for FILE in *; do grep -q foo $FILE && grep -q 321 $FILE && echo $FILE; done 

grep renvoie 0 (true) sil a trouvé la chaîne et le && séparant les commandes signifie que le second ne fonctionnera que si le premier était vrai. Loption -q garantit que grep naffiche rien.

Lécho ne sexécutera que si les deux chaînes étaient trouvé dans le même fichier.


Jai pensé à une manière différente de le faire. Cette méthode sera probablement plus efficace si les fichiers en question sont plus volumineux que votre RAM installée car il suffit de grep à travers chaque fichier une fois.

 for FILE in * do test $(egrep -o "foo|321" $FILE | uniq | sort | uniq | wc -l) -eq 2 && echo $FILE done 

et la version sur une ligne:

 for FILE in *; do test $(egrep -o "foo|321" $FILE | uniq | sort | uniq | wc -l) -eq 2 && echo $FILE; done 

Commentaires

  • Pour votre solution plus efficace: que se passe-t-il si le fichier contient " foo foo "?
  • Cela ' est à quoi sert uniq | sort | uniq. " foo foo " finit par être une ligne mais " foo 321 " finit par être deux lignes car grep -o renvoie toutes les chaînes trouvées sur des lignes séparées, même si elles ont commencé sur la même ligne.
  • Si les fichiers deviennent si volumineux quil serait acceptable de bifurquer au moins six fois par fichier, il est probablement logique dutiliser awk à la place afin que les fichiers naient pas besoin dêtre recherchés jusquà la fin.
  • @Ladadadada a obtenu il. 🙂
  • @HaukeLaging grep -q et grep -l ne recherche pas jusquà la fin du fichier: ils sortent aussitôt comme une correspondance est trouvée. Je me demande pourquoi la première solution nest pas ' t for FILE in *; do grep -q foo "$FILE" && grep -l 321 "$FILE"; done

Réponse

Étrange. Pour moi, les deux variantes fonctionnent (grep (GNU grep) 2.13):

grep "foo\|321" grep -E "foo|321" 

Edit 1 – afficher les fichiers avec les deux correspondances uniquement

La réponse for file in * fonctionne mais peut devenir un cauchemar de performances (pour de grandes quantités de fichiers ): au moins deux processus par fichier. Cest plus rapide (dans le monde GNU):

find . -type f -print0 | xargs -0 -r grep --files-with-matches --null -- string1 | xargs -0 -r grep --files-with-matches -- string2 

string1 devrait être celui qui donne le moins de correspondances.

Commentaires

  • Le demandeur recherche le résultat à renvoyer vrai uniquement si un fichier contient les deux chaînes plutôt que sil ne correspond quà au moins une.
  • Jaime ça Option --files-with-matches. Lisez-le simplement dans la page de manuel et cela provoque larrêt de grep après avoir trouvé la première correspondance, ce qui signifie quil est ' très efficace pour les gros fichiers si la correspondance se produit tôt. Il indique également que loption courte -l est spécifiée par POSIX, elle peut donc être utilisée en dehors du monde GNU.
  • @Ladadadada Lefficacité nest pas un avantage sur votre -q, cependant. En mentionnant GNU, je ne pensais pas ' à –files-with-matches mais à -0 / –null.Ce qui me vient à lesprit: lexpansion des chemins contient un tri alphabétique (vraiment mauvais: il semble que ' t même pas être désactivé) donc pour dénormes quantités de fichiers, même votre for file in * cesse vraiment dêtre amusant.
  • En effet, les optimisations defficacité seraient assez différentes pour quelques gros fichiers par rapport à beaucoup de petits et * juste ' ne fonctionnera pas du tout après quelques milliers de fichiers.
  • @Ladadadada Cela ne ' t fonctionne dans le cadre dune ligne de commande pour une commande externe: grep foo * Mais for file in * est une structure interne au shell donc je suppose que la limite de ligne de commande nest pas applicable ici.

Réponse

En gros, pour trouver tous les fichiers, y compris un chaîne dans un répertoire, vous pouvez utiliser:

grep -lir "pattern" /path/to/the/dir 
  • -l: pour effectuer cette analyse sarrêtera sur la première correspondance
  • -i: pour ignorer les distinctions de casse dans le modèle et les fichiers dentrée
  • -r: recherchez tous les fichiers sous le répertoire, de manière récursive

Pour rechercher deux modèles, essayez ceci:

grep -lr "321" $(grep -lr "foo" /path/to/the/dir) 

Commentaires

  • Les commentaires ennuyeux standard sur $() ne gérant pas bien les espaces sappliquent. En pratique, pour une doublure au niveau du shell, cette commande fonctionnera correctement.

Réponse

Devrait être

grep -e "foo" -e "321" * 

Utilisez -e pour plusieurs modèles

EDIT

Au cas où vous auriez besoin des deux pour correspondre:

grep -e ".*foo.*321.*" * 

Si lordre na pas dimportance:

grep -e ".*foo.*321.*" ".*321.*foo.*" * 

Commentaires

  • Cela ne fournit pas de réponse à la question. Pour critiquer ou demander des éclaircissements à un auteur, laissez un commentaire sous son message.
  • @mdpc Je pense que cela fournit une réponse. Quest-ce qui vous fait penser différemment?
  • @HaukeLaging Parce quil renvoie si lun des motifs correspond. LOP recherche un cas où il ne renvoie vrai que si les deux sont trouvés dans le fichier.
  • Daprès ce que je comprends, cela ne trouve que les fichiers où les deux chaînes contiennent sur la même ligne (je don ' t pense. correspond aux nouvelles lignes par défaut)

Laisser un commentaire

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