2012-06-10 15 views
8

Desidero ottenere le query "GET" dai registri del server.Uso di grep per ottenere la WORD successiva dopo una corrispondenza in ogni riga

Per esempio, questo è il log del server

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 - 

Quando provo con semplice grep o awk,

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

dà fuori

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 - 

voglio solo visualizzare : ciao e ss

Esiste un modo per procedere?

risposta

8

si Supponendo che hanno grep GNU, è possibile utilizzare perl-style regex per fare un lookbehind positiva:

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

Se non si dispone di grep GNU, quindi vorrei consigliare solo usando sed:

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

Se vi capita di avere GNU sed (che sarebbe strano se non si dispone di grep GNU ma hanno GNU sed), che può essere notevolmente semplificata:

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

La linea di fondo qui è, certamente non hai bisogno di tubi per realizzare questo. grep o sed saranno sufficienti.

+0

Fantastico. Funziona perfettamente !! Breve e semplice –

5

In questo caso poiché il file di registro ha una struttura nota, un'opzione è di utilizzare cut per estrarre la settima colonna (i campi sono contrassegnati dalle schede di default).

grep GET log.txt | cut -f 7 
+0

Mostra ancora l'intera linea. 1.0.0.127.in-addr.arpa - - [10/Jun/2012 15:32:27] "OTTIENI/hello HTTP/1.1" 404 - 1.0.0.127.in-addr.arpa - - [10/Jun/2012 15:41:57] "GET/ss HTTP/1.1" 404 - –

+0

Hmmm, è lo spazio o la scheda separati? Se lo spazio, utilizzare '-d ''' con taglio per specificare lo spazio come delimitatore di colonna. –

+0

Funziona alla grande con il parametro ** - d '' **. –

1

Spesso è più semplice utilizzare una pipeline piuttosto che una singola espressione regolare complessa. Questo funziona sui dati che hai fornito:

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

Questo gasdotto restituisce i seguenti risultati:

hello 
ss 

Ci sono certamente altri modi per ottenere il lavoro fatto, ma questo funziona palesemente sul corpus fornito.

2

utilizzare un tubo se si utilizza grep:

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

[^ /] significa estrarre le lettere dopo^simbolo dall'uscita grep

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

Se avete gawk poi sopra il comando utilizzerà match per selezionare il valore desiderato usando regex e memorizzandolo su un array a.

0

stavo cercando di fare questo e sono imbattuto in questo link: https://www.unix.com/shell-programming-and-scripting/153101-print-next-word-after-found-pattern.html

Sommario: uso grep per trovare le linee corrispondenti, quindi usare awk per trovare il modello e stampare il campo successivo:

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

Se si desidera conoscere le occorrenze univoche:

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