web-dev-qa-db-fra.com

grepping en utilisant le résultat de grep précédent

Existe-t-il un moyen d’effectuer un grep en fonction des résultats d’un précédent, au lieu de simplement empiler plusieurs greps les uns dans les autres. Par exemple, disons que j'ai la sortie du fichier journal ci-dessous:

ID 1000 xyz occured
ID 1001 misc content
ID 1000 misc content
ID 1000 status code: 26348931276572174
ID 1000 misc content
ID 1001 misc content

Pour commencer, je voudrais grep le fichier de journal entier pour voir si "xyz s'est produit" est présent. Si c'est le cas, j'aimerais obtenir le numéro d'identification de cet événement et grep via toutes les lignes du fichier portant ce numéro d'identification, à la recherche du code d'état.

J'imaginais pouvoir utiliser xargs ou quelque chose du genre, mais je n'arrive pas à le faire fonctionner.

grep "xyz occured" file.log | awk '{ print $2 }' | xargs grep "status code" | awk '{print $NF}'

Des idées sur comment faire cela?

14
Chris Robinson

Tu y es presque. Mais si xargs peut parfois être utilisé pour faire ce que vous voulez (en fonction de la façon dont la commande suivante prend ses arguments), vous ne l'utilisez pas réellement pour grep pour l'ID que vous venez d'extraire. Ce que vous devez faire, c'est prendre la sortie du premier grep (contenant le code d'identification) et l'utiliser dans la prochaine expression de grep. Quelque chose comme:

grep "^ID `grep 'xyz occured' file.log | awk '{print $2}'` status code" file.log

Évidemment, une autre option serait d'écrire un script pour le faire en un seul passage, comme le suggère Ed.

6
Andy Ross

Une réponse générale pour grep-ing la sortie grep-ed: 

grep 'patten1' *.txt | grep 'pattern2' 

remarquez que le second grep ne pointe pas sur un fichier. 

En savoir plus sur les trucs cool de grep ici

19
ab-user

Grep le résultat d'un précédent Grep:

Étant donné le contenu de ce fichier:

ID 1000 xyz occured
ID 1001 misc content
ID 1000 misc content
ID 1000 status code: 26348931276572174
ID 1000 misc content
ID 1001 misc content

Cette commande:

grep "xyz" file.log | awk '{ print $2 }' > f.log; grep `cat f.log` file.log;

renvoie ceci:

ID 1000 xyz occured
ID 1000 misc content
ID 1000 status code: 26348931276572174
ID 1000 misc content

Il recherche "xyz" dans fichier.log place le résultat dans f.log. Puis greps pour cet identifiant dans file.log. Si le grep externe renvoie plusieurs identifiants, alors le grep interne ne cherchera que le premier identifiant et les autres en erreur.

1
Eric Leschinski

Encore une autre façon

for x in `grep "xyz occured" file.log | cut -d\  -f2`
do
  grep $x file.log
done

Ce que j’aime dans cette méthode, c’est que si vous le vouliez, vous pourriez écrire la sortie dans un fichier pour chaque code de statut.

grep $x file.log >> /var/tmp/$x.out
1
madflojo

Il suffit d'utiliser awk:

awk '{info[$2] = info[$2] $0 ORS} /xyz occured/{ids[$2]} END{ for (id in ids) printf "%s",info[id]}' file.log

ou:

awk '/status code/{code[$2]=$NF} /xyz occured/{ids[$2]} END{ for (id in ids) print code[id]}' file.log

en fonction de ce que vous voulez vraiment sortir. Certains résultats attendus dans votre question pourraient aider.

1
Ed Morton

Il s’agit simplement de récupérer les fichiers dans une zone de recherche plus étroite. Dans votre cas, l'étendue de la recherche est déterminée par le contenu du fichier. 

J'ai trouvé ce problème plus souvent tout en réduisant l'étendue de la recherche grâce à de nombreuses recherches (application de filtres aux résultats précédents de grep). 

Essayer de trouver une réponse générale:

1) Générez une liste avec le résultat du premier grep:

grep pattern | awk -F':' '{print $1}'

2) Deuxième grep dans la liste des fichiers comme ici

xargs grep -i pattern

3) appliquez ce filtre en cascade les fois où vous avez juste besoin d’ajouter awk pour n’obtenir que les noms de fichiers et xargs pour les transférer à grep -i 

Par exemple:

grep 'pattern1' | awk -F':' '{print $1}' | xargs grep -i 'pattern2'
0
yucer