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 tcp
o udp
seguida 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 grep
el anterior, o puede usar
sed -n '/^proto=/{ s/^[^=]*=//; s/[[:blank:]].*//; p; }' file
Aquí, suprimimos la salida predeterminada con la -n
opció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 grep
el anterior, o puede usar
awk '/^proto=/ { split($1, a, "="); print a[2] }' file
Respuesta2
Si está en GNU grep (para la -P
opció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 \K
bandera.
Lo anterior supone que las columnas están separadas por espacios. Si las tabulaciones también son un separador válido, las usaría \S
para 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 \b
la 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 proto
de la primera columna.
sub(/proto=/, "")
se eliminará proto=
de la entrada
print $1
imprime la columna restante
$ awk '$1 ~ "proto" { sub(/proto=/, ""); print $1 }' input
tcp/http
tcp/https
udp/dns
Respuesta4
Sólo otra grep
solución:
grep -o '[^=/]\+/[^ ]\+' file
Y uno similar sed
imprimiendo solo el grupo capturado coincidente:
sed -n 's/.*=\([^/]\+\/[^ ]\+\).*/\1/p' file