Comment puis-je grep pour les lignes qui contiennent deux mots d'entrée sur la ligne? Je cherche des lignes qui contiennent les deux mots, comment puis-je le faire? J'ai essayé la pipe comme ça:
grep -c "Word1" | grep -r "Word2" logs
Il se bloque juste après la première commande de pipe.
Pourquoi?
Pourquoi passez-vous -c
? Cela montrera simplement le nombre de matchs. De même, il n'y a aucune raison d'utiliser -r
. Je vous suggère de lire man grep
.
Pour grep pour 2 mots existant sur la même ligne, il suffit de faire:
grep "Word1" FILE | grep "Word2"
grep "Word1" FILE
imprimera toutes les lignes contenant Word1 à partir de FILE, puis grep "Word2"
imprimera les lignes contenant Word2. Par conséquent, si vous les combinez à l'aide d'un tuyau, des lignes contenant Word1 et Word2 s'afficheront.
Si vous voulez juste compter le nombre de lignes contenant les 2 mots sur la même ligne, faites:
grep "Word1" FILE | grep -c "Word2"
Aussi, pour répondre à votre question, pourquoi est-il bloqué: dans grep -c "Word1"
, vous n'avez pas spécifié de fichier. Par conséquent, grep
attend une entrée de stdin
, raison pour laquelle il semble se bloquer. Vous pouvez appuyer sur Ctrl+D pour envoyer un EOF (fin de fichier) afin qu'il se ferme.
Une réécriture simple de la commande dans la question est la suivante:
grep "Word1" logs | grep "Word2"
Le premier grep
recherche les lignes avec 'Word1' dans le fichier 'logs', puis les insère dans le second grep
qui recherche les lignes contenant 'Word2'.
Cependant, il n'est pas nécessaire d'utiliser deux commandes comme ça. Vous pouvez utiliser étendu grep
(grep -E
ou egrep
):
grep -E 'Word1.*Word2|Word2.*Word1' logs
Si vous savez que 'Word1' précédera le mot 'Word2' sur la ligne, vous n'avez même pas besoin des alternatives et des fonctions normales grep
suffiraient:
grep 'Word1.*Word2' logs
Les variantes "une commande" présentent l'avantage de ne comporter qu'un seul processus en cours d'exécution. Par conséquent, les lignes contenant "Word1" ne doivent pas nécessairement être transmises via un canal au processus secondaire. Cela dépend de la taille du fichier de données et du nombre de lignes correspondant à "Word1". Si le fichier est petit, les performances risquent de ne pas être un problème et l'exécution de deux commandes convient. Si le fichier est volumineux mais que quelques lignes contiennent "Word1", peu de données seront transmises sur le canal et l'utilisation de deux commandes est acceptable. Toutefois, si le fichier est volumineux et que 'Word1' apparaît fréquemment, vous risquez alors de transmettre des données significatives en aval, où une seule commande évite cette surcharge. Contre cela, la regex est plus complexe; vous devrez peut-être effectuer une analyse comparative pour déterminer ce qui convient le mieux, mais uniquement si la performance compte vraiment. Si vous exécutez deux commandes, essayez de sélectionner le mot le moins fréquent dans la première grep
afin de minimiser la quantité de données traitées par la seconde.
Le script initial est:
grep -c "Word1" | grep -r "Word2" logs
C'est une séquence de commande étrange. La première grep
va compter le nombre d'occurrences de 'Word1' sur son entrée standard et l'imprimer sur sa sortie standard. Jusqu'à ce que vous indiquiez EOF (par exemple en tapant Control-D), il restera assis à attendre que vous tapiez quelque chose. Le second grep
effectue une recherche récursive sur '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, cela échouera car il n'y a ni fichier ni répertoire nommé logs
où je suis en train d'exécuter le pipeline. Notez que la seconde grep
ne lit pas du tout son entrée standard, le tuyau est donc superflu.
Avec Bash, le shell parent attend la fin de tous les processus du pipeline. Il attend donc que le grep -c
se termine, ce qui ne se fera pas tant que vous n’indiquerez pas EOF. Par conséquent, votre code semble rester bloqué. Avec Heirloom Shell , la seconde grep
se termine et se termine, et le shell invite à nouveau. Maintenant, vous avez deux processus en cours d'exécution, le premier grep
et le shell. Ils tentent tous deux de lire à partir du clavier. Il n'est pas possible de déterminer laquelle obtiendra une ligne d'entrée donnée (ni un EOF indication).
Notez que même si vous saisissiez des données en entrée dans le premier grep
, vous n'obtiendrez que les lignes contenant "Word2" affichées dans 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.
vous pourriez utiliser awk. comme ça...
cat <yourFile> | awk '/Word1/ && /Word2/'
L'ordre n'est pas important. Donc, si vous avez un fichier et ...
un fichier nommé, fichier1 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
ensuite,
/tmp$ cat file1| awk '/Word1/ && /Word2/'
aura pour résultat,
Word1 is in this file as well as Word2
Word2 is in this file as well as Word1
oui, awk est plus lent.
Le problème principal est que vous n’avez fourni aucune entrée au premier grep. Vous aurez besoin de réorganiser votre commande quelque chose comme
grep "Word1" logs | grep "Word2"
Si vous voulez compter les occurrences, mettez un '-c' sur le second grep.
Vous chat essayez avec la commande ci-dessous
cat log|grep -e Word1 -e Word2
grep Word1 file_name | grep Word2
cela semble être le moyen le plus facile pour moi
Utilisez grep:
grep -wE "string1|String2|...." file_name
Ou vous pouvez utiliser:
echo string | grep -wE "string1|String2|...."