grep pour 2 mots existant sur la même ligne

Comment puis-je faire pour les lignes qui contiennent deux mots d'entrée sur la ligne? Je cherche des lignes qui contiennent les deux mots, comment je fais ça? J'ai essayé pipe comme ceci:

 grep -c "word1" |grep -r "word2" logs

il STACKS juste après la première commande de pipe. pourquoi?

85
demandé sur houbysoft 2011-06-26 01:36:10

8 réponses

pourquoi passez-vous -c ? Ça montrera juste le nombre de matchs. De même, il n'y a aucune raison d'utiliser -r . Je vous suggère de lire man grep .

grep pour 2 mots existants sur la même ligne, il suffit de faire:

grep "word1" FILE | grep "word2"

grep "word1" FILE affichera toutes les lignes qui contiennent word1 à partir du fichier, puis grep "word2" affichera les lignes qui contiennent word2. Par conséquent, si vous les combinez en utilisant un tuyau, il sera afficher les lignes contenant à la fois le mot1 et mot2.

si vous voulez juste un compte de combien de lignes ont les 2 mots sur la même ligne, faites:

grep "word1" FILE | grep -c "word2"

Aussi, pour répondre à votre question, pourquoi est-il coincé : grep -c "word1" , vous n'avez pas spécifié d'un fichier. Par conséquent, grep s'attend à des entrées de stdin , c'est pourquoi il semble suspendu. Vous pouvez appuyer sur Ctrl + D pour envoyer un EOF (fin de fichier) ainsi qu'il se ferme.

125
répondu houbysoft 2011-06-26 04:03:25

Prescription

une réécriture simple de la commande dans la question Est:

grep "word1" logs | grep "word2"

le premier grep trouve les lignes avec" word1 "dans le fichier "logs" et les alimente ensuite dans le second grep qui cherche les lignes contenant "word2".

Cependant, il n'est pas nécessaire d'utiliser deux commandes comme ça. Vous pouvez utiliser grep ( grep -E ou egrep ):

grep -E 'word1.*word2|word2.*word1' logs

si vous savez que "word1" précédera "word2" sur la ligne, vous n'avez même pas besoin des alternatives et régulier grep ferait:

grep 'word1.*word2' logs

les variantes ' one command 'ont l'avantage qu'il n'y a qu'un seul processus en cours, et donc les lignes contenant' word1 ' ne doivent pas être passées par un tuyau au second processus. Combien cette matière dépend de la taille du fichier de données et du nombre de lignes correspondent 'mot1'. Si le fichier est petite, la performance n'est pas susceptible d'être un problème et l'exécution de deux commandes est très bien. Si le fichier est gros mais que seulement quelques lignes contiennent 'word1', il n'y aura pas beaucoup de données transmises sur le tuyau et l'utilisation de deux commandes est très bien. Cependant, si le fichier est énorme et 'word1' se produit fréquemment, alors vous pouvez passer des données significatives dans le tuyau où une seule commande évite cette surabondance. Par contre, le regex est plus complexe; vous pourriez avoir besoin de le comparer pour savoir ce qui est le mieux - mais seulement si la performance compte vraiment. Si vous lancez deux commandes, vous devriez vous efforcer de sélectionner le mot le moins fréquemment utilisé dans le premier grep pour minimiser la quantité de données traitées par le second.

diagnostic

le script initial est:

grep -c "word1" | grep -r "word2" logs

c'est une séquence de commande étrange. Le premier grep va compter le nombre d'occurrences de 'mot1' sur son entrée standard, et d'imprimer ce numéro sur son la sortie standard. Jusqu'à ce que vous indiquiez EOF (par exemple en tapant Control-d ), il restera là, attendant que vous tapiez quelque chose. Le second grep effectue une recherche récursive de" word2 "dans les fichiers situés sous le répertoire logs (ou, s'il s'agit d'un fichier, dans le fichier logs ). Ou, dans mon cas, il échouera puisqu'il n'y a pas de fichier ou de répertoire appelé logs où je dirige le pipeline. Notez que le second grep ne lit pas son l'entrée standard, de sorte que le tuyau est superflu.

avec Bash, le shell parent attend jusqu'à ce que tous les processus dans le pipeline aient quitté, donc il attend autour de lui que le grep -c soit terminé, ce qu'il ne fera pas jusqu'à ce que vous indiquiez EOF. Par conséquent, votre code semble coincé. Avec Heirloom Shell , le second grep se termine et sort, et le shell invite à nouveau. Maintenant vous avez deux processus en cours d'exécution ,le premier grep et le shell, et ils sont tous les deux en train d'essayer de lire à partir du clavier, et il n'est pas déterminé qui on obtient une ligne donnée d'entrée (ou une indication de foe donnée).

notez que même si vous tapiez des données en entrée dans le premier grep , vous obtiendriez seulement n'importe quelles lignes qui contiennent 'word2' montré sur la sortie.


note de bas de page:

à un moment donné, la réponse utilisée:

grep -E 'word1.*word2|word2.*word1' "$@"
grep 'word1.*word2' "$@"

Cela a déclenché les commentaires ci-dessous.

55
répondu Jonathan Leffler 2015-09-09 16:49:25

vous pourriez utiliser awk. pareil...

cat <yourFile> | awk '/word1/ && /word2/'

L'ordre n'est pas important. Donc, si vous avez un fichier et...

un fichier nommé, file1 contient:

word1 is in this file as well as word2
word2 is in this file as well as word1
word4 is in this file as well as word1
word5 is in this file as well as word2

puis,

/tmp$ cat file1| awk '/word1/ && /word2/'

résultera en,

word1 is in this file as well as word2
word2 is in this file as well as word1

Oui, awk est plus lent.

8
répondu Colin MacKenzie - III 2014-06-03 13:42:39

le problème principal est que vous n'avez pas fourni le premier grep avec aucune entrée. Vous aurez besoin de réorganiser votre commande quelque chose comme

grep "word1" logs | grep "word2"

si vous voulez compter les occurences, alors mettez un '-c' sur le second grep.

7
répondu sysboy 2013-03-07 14:55:51

Vous chat essayer avec la commande ci-dessous

cat log|grep -e word1 -e word2
5
répondu user2724604 2013-08-28 11:25:17

grep word1 file_name | grep word2

qui semble être le moyen le plus facile pour moi

2
répondu user4813867 2015-04-21 08:57:21

Utiliser grep:

grep -wE "string1|String2|...." file_name

ou vous pouvez utiliser:

echo string | grep -wE "string1|String2|...."
1
répondu HARSH 2015-06-02 15:50:42

pour saisir deux mots à la fois, utilisez cette commande shell:

eval "</dev/stdin $(printf "|grep '%s'" word1 word2)" FILE

si vous utilisez ceci plus souvent, cela peut être défini comme un alias:

alias grep-all="</dev/stdin $(printf "|grep '%s'" word1 word2)"

alors exécutez juste:

grep-all FILE

si vous avez plusieurs modèles stockés dans le fichier, voir: Match tous les modèles du fichier à la fois .

vérifiez aussi: comment exécuter grep avec multiple et patterns?

0
répondu kenorb 2017-04-13 12:36:24