2012-06-10 12 views
8

Quiero obtener las consultas "GET" de los registros de mi servidor.Usando grep para obtener la próxima PALABRA después de una coincidencia en cada línea

Por ejemplo, este es el registro del servidor

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 - 

Cuando trato con grep simple o awk,

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

que da hacia fuera

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 - 

sólo quiero mostrar : hola y ss

¿Hay alguna manera de que esto se pueda hacer?

Respuesta

8

Asumiendo que tienen grep de GNU, puede utilizar expresiones regulares al estilo Perl para hacer una búsqueda hacia atrás positivo:

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

Si usted no tiene grep de GNU, entonces yo aconsejaría simplemente usando sed:

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

Si le sucede que tiene sed de GNU (que sería extraño si no tienen grep de GNU, pero tienen sed de GNU), que se puede simplificar en gran medida:

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

La conclusión es que, sin duda, no necesita tuberías para lograr esto. grep o sed solo serán suficientes.

+0

Impresionante. ¡¡Funciona perfectamente!! Corto y simple. –

5

En este caso, dado que el archivo de registro tiene una estructura conocida, una opción es usar cut para extraer la séptima columna (los campos se indican mediante pestañas de manera predeterminada).

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

Mostrando toda la línea. 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 - –

+0

Hmmm, ¿está separado el espacio o la pestaña? Si tiene espacio, use '-d ''' con corte para especificar el espacio como el delimitador de la columna. –

+0

Funciona muy bien con el parámetro ** - d '' **. –

1

A menudo es más fácil utilizar una interconexión en lugar de una sola expresión regular compleja. Esto funciona en los datos que nos ha facilitado:

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

Esta tubería devuelve los siguientes resultados:

hello 
ss 

Es cierto que hay otras maneras de hacer el trabajo, pero esto funciona patentemente en el corpus proporcionado.

2

utilizar una tubería de si utiliza grep:

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

[^ /] El extracto de las letras después de^símbolo de la salida de grep

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

Si tiene gawk entonces por encima de comando utilizará match para seleccionar el valor deseado usando regex y almacenarlo en una matriz a.

0

yo estaba tratando de hacer esto y me encontré con este enlace: https://www.unix.com/shell-programming-and-scripting/153101-print-next-word-after-found-pattern.html

Resumen: uso grep para encontrar las líneas que coincidan, a continuación, utilizar awk para encontrar el patrón e imprimir el siguiente campo:

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

Si desea conocer las ocurrencias únicas:

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