Grep Coincidir y extraer

Grep Coincidir y extraer

Tengo un archivo que contiene líneas como

proto=tcp/http  sent=144        rcvd=52 spkt=3 
proto=tcp/https  sent=145        rcvd=52 spkt=3
proto=udp/dns  sent=144        rcvd=52 spkt=3

Necesito extraer el valor de proto que es tcp/http,, tcp/https.udp/dns

Hasta ahora he intentado esto grep -o 'proto=[^/]*/'pero solo he podido extraer el valor como proto=tcp/.

Respuesta1

Con grep -o, tendrás que hacer coincidir exactamente lo que quieres extraer. Como no desea extraer la proto=cadena, no debe hacerla coincidir.

Una expresión regular extendida que coincidiría con una barra tcpo udpseguida por una barra y alguna cadena alfanumérica no vacía es

(tcp|udp)/[[:alnum:]]+

Aplicando esto en sus datos:

$ grep -E -o '(tcp|udp)/[[:alnum:]]+' file
tcp/http
tcp/https
udp/dns

Para asegurarnos de que solo hagamos esto en líneas que comiencen con la cadena proto=:

grep '^proto=' file | grep -E -o '(tcp|udp)/[[:alnum:]]+'

Con sed, eliminando todo lo que hay antes del primer =y después del primer carácter en blanco:

$ sed 's/^[^=]*=//; s/[[:blank:]].*//' file
tcp/http
tcp/https
udp/dns

Para asegurarnos de que solo hagamos esto en líneas que comiencen con la cadena proto=, puede insertar el mismo paso de preprocesamiento que grepel anterior, o puede usar

sed -n '/^proto=/{ s/^[^=]*=//; s/[[:blank:]].*//; p; }' file

Aquí, suprimimos la salida predeterminada con la -nopción y luego activamos las sustituciones y una impresión explícita de la línea solo si la línea coincide ^proto=.


Con awk, usando el separador de campos predeterminado y luego dividiendo el primer campo =e imprimiendo el segundo bit:

$ awk '{ split($1, a, "="); print a[2] }' file
tcp/http
tcp/https
udp/dns

Para asegurarnos de que solo hagamos esto en líneas que comiencen con la cadena proto=, puede insertar el mismo paso de preprocesamiento que grepel anterior, o puede usar

awk '/^proto=/ { split($1, a, "="); print a[2] }' file

Respuesta2

Si está en GNU grep (para la -Popción), puede usar:

$ grep -oP 'proto=\K[^ ]*' file
tcp/http
tcp/https
udp/dns

Aquí hacemos coincidir la proto=cadena para asegurarnos de que estamos extrayendo la columna correcta, pero luego la descartamos de la salida con la \Kbandera.

Lo anterior supone que las columnas están separadas por espacios. Si las tabulaciones también son un separador válido, las usaría \Spara hacer coincidir los caracteres que no son espacios en blanco, por lo que el comando sería:

grep -oP 'proto=\K\S*' file

Si también desea protegerse contra campos coincidentes donde proto=hay una subcadena, como a thisisnotaproto=tcp/https, puede agregar un límite de palabra de \bla siguiente manera:

grep -oP '\bproto=\K\S*' file

Respuesta3

Usando awk:

awk '$1 ~ "proto" { sub(/proto=/, ""); print $1 }' input

$1 ~ "proto"Nos aseguraremos de que solo tomemos medidas en las líneas protode la primera columna.

sub(/proto=/, "")se eliminará proto=de la entrada

print $1imprime la columna restante


$ awk '$1 ~ "proto" { sub(/proto=/, ""); print $1 }' input
tcp/http
tcp/https
udp/dns

Respuesta4

Sólo otra grepsolución:

grep -o '[^=/]\+/[^ ]\+' file

Y uno similar sedimprimiendo solo el grupo capturado coincidente:

sed -n 's/.*=\([^/]\+\/[^ ]\+\).*/\1/p' file

información relacionada