web-dev-qa-db-fra.com

Utiliser grep pour obtenir le prochain mot après une correspondance dans chaque ligne

Je souhaite obtenir les requêtes "GET" à partir des journaux de mon serveur. 

Par exemple, ceci est le journal du serveur

1.0.0.127.in-addr.arpa - - [10/Jun/2012 15:32:27] code 404, message File not fo$
1.0.0.127.in-addr.arpa - - [10/Jun/2012 15:32:27] "GET /hello HTTP/1.1" 404 -   
1.0.0.127.in-addr.arpa - - [10/Jun/2012 15:41:57] code 404, message File not fo$
1.0.0.127.in-addr.arpa - - [10/Jun/2012 15:41:57] "GET /ss HTTP/1.1" 404 -

Quand j'essaye avec grep ou awk, 

Adi:~ adi$ awk '/GET/, /HTTP/' serverlogs.txt

il donne

1.0.0.127.in-addr.arpa - - [10/Jun/2012 15:32:27] "GET /hello HTTP/1.1" 404 -
1.0.0.127.in-addr.arpa - - [10/Jun/2012 15:41:57] "GET /ss HTTP/1.1" 404 -

Je veux juste afficher: bonjour et ss

Y a-t-il un moyen de faire cela?

11
aditya.gupta

En supposant que vous avez gnu grep, vous pouvez utiliser une expression rationnelle de style Perl pour effectuer une recherche positive:

grep -oP '(?<=GET\s/)\w+' file

Si vous n'avez pas gnu grep, je vous conseillerais simplement d'utiliser sed:

sed -n '/^.*GET[[:space:]]\{1,\}\/\([-_[:alnum:]]\{1,\}\).*$/s//\1/p' file

Si vous vous en apercevez, cela peut être grandement simplifié:

sed -n '/^.*GET\s\+\/\(\w\+\).*$/s//\1/p' file

En fin de compte, vous n’avez certainement pas besoin de tuyaux pour accomplir cela. grep ou sed seul suffira.

12
Tim Pote

Dans ce cas, étant donné que le fichier journal a une structure connue, une option consiste à utiliser cut pour extraire la 7ème colonne (les champs sont désignés par défaut par des onglets).

grep GET log.txt | cut -f 7 
6
John Carter

utilisez un tuyau si vous utilisez grep:

grep -o /he.* log.txt | grep -o [^/].*
grep -o /ss log.txt | grep -o [^/].*

[^ /] signifie extraire les lettres après le symbole ^ de la sortie de grep

3
Charles Chow

J'essayais de le faire et suis tombé sur ce lien: https://www.unix.com/Shell-programming-and-scripting/153101-print-next-Word-after-found-pattern.html

Résumé: Utilise grep pour trouver les lignes correspondantes, puis utilise awk pour trouver le motif et imprimer le champ suivant:

grep pattern logfile | \
  awk '{for(i=1; i<=NF; i++) if($i~/pattern/) print $(i+1)}'

Si vous voulez connaître les occurrences uniques:

grep pattern logfile | \
  awk '{for(i=1; i<=NF; i++) if($i~/pattern/) print $(i+1)}' | \
  sort | \
  uniq -c
2
ajp619

Il est souvent plus facile d'utiliser un pipeline plutôt qu'une seule expression régulière complexe. Cela fonctionne sur les données que vous avez fournies:

fgrep GET /tmp/foo | 
    egrep -o 'GET (.*) HTTP' |
    sed -r 's/^GET \/(.+) HTTP/\1/'

Ce pipeline renvoie les résultats suivants:

hello
ss

Il y a certainement d'autres moyens de faire le travail, mais cela fonctionne manifestement sur le corpus fourni.

1
Todd A. Jacobs
gawk '{match($7,/\/(\w+)/,a);} length(a[1]){print a[1]}' log.txt
hello
ss

Si vous avez gawk, la commande ci-dessus utilisera la fonction match pour sélectionner la valeur souhaitée à l'aide de l'expression rationnelle et la stocker dans un tableau a

0
PS.