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/
.
sed
,awk
operl
nogrep
.Respuestas:
Asumiendo que esto está relacionado con su pregunta anterior , está yendo por el camino equivocado. En lugar de tratar de juntar fragmentos de guiones que hagan lo que quieras la mayor parte del tiempo y necesiten obtener un guión completamente diferente cada vez que necesites hacer algo lo más mínimo posible, solo crea 1 guión que pueda analizar tu ingrese el archivo en una matriz (a
f[]
continuación) que asigna sus nombres de campo (etiquetas) a sus valores y luego puede hacer lo que quiera con el resultado, por ejemplo, dado este archivo de entrada de su pregunta anterior:podemos escribir un script awk que cree una matriz de los valores indexados por sus nombres / etiquetas:
y dado que puede hacer lo que quiera con sus datos simplemente haciendo referencia a ellos por los nombres de campo, por ejemplo, usando GNU awk
-e
para facilitar la mezcla de un script en un archivo con un script de línea de comandos:fuente
perl
puede ser más fácil de usar.awk
y lossed
scripts generalmente son más simplesperl
porque es esencialmente un superconjunto de ellos, con características adicionales para tareas comunes.s/old/new/g
y que sed no sea awk, así que dejemos eso de lado. No estoy de acuerdo con que los scripts de awk complejos sean más simples en perl. Pueden ser más breves, por supuesto, pero la brevedad no es un atributo deseable del software, la concisión lo es, y es extremadamente raro que tengan algún beneficio real, además de que generalmente son mucho más difíciles de leer, por eso la gente publica cosas como zoitz.com / archivos / 13 sobre perl y se refieren a él como un lenguaje de solo escritura, a diferencia de awk. Sin embargo, todavía me gustaría ver un perl equivalente a estoCon
grep -o
, tendrá que coincidir exactamente con lo que desea extraer. Como no desea extraer laproto=
cadena, no debe coincidir con ella.Una expresión regular extendida que coincidiría con
tcp
oudp
seguida de una barra y alguna cadena alfanumérica no vacía esAplicando esto en sus datos:
Para asegurarnos de que solo hacemos esto en las líneas que comienzan con la cadena
proto=
:Con
sed
, eliminar todo antes del primer=
y después del primer carácter en blanco:Para asegurarse de que solo hacemos esto en las líneas que comienzan con la cadena
proto=
, puede insertar el mismo paso de preprocesamiento con elgrep
anterior, o puede usarAquí, 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 campo predeterminado, y luego dividiendo el primer campo=
e imprimiendo el segundo bit:Para asegurarse de que solo hacemos esto en las líneas que comienzan con la cadena
proto=
, puede insertar el mismo paso de preprocesamiento con elgrep
anterior, o puede usarfuente
Si está en GNU grep (para la
-P
opción), puede usar:Aquí hacemos coincidir la
proto=
cadena, para asegurarnos de que estamos extrayendo la columna correcta, pero luego la descartamos de la salida con el\K
bandera.Lo anterior supone que las columnas están separadas por espacios. Si las pestañas también son un separador válido, lo usaría
\S
para hacer coincidir los caracteres que no son espacios en blanco, por lo que el comando sería:Si también desea protegerse contra los campos de coincidencia donde
proto=
hay una subcadena, como athisisnotaproto=tcp/https
, puede agregar un límite de palabra de la siguiente\b
manera:fuente
grep -oP 'proto=\K\S+'
. Elproto=tcp/http
puede ir seguida de una pestaña en lugar de espacios, y la\S
diferencia[^ ]
coincidirá con cualquier carácter que no sea espacio.-o
es un GNUismo.-P
solo es compatible con GNUgrep
si está construido con soporte PCRE (opcional en tiempo de compilación).Utilizando
awk
:$1 ~ "proto"
se asegurará de que solo tomemos medidas en líneas conproto
de la primera columnasub(/proto=/, "")
removeráproto=
de la entradaprint $1
imprime la columna restantefuente
Código de golf en las
grep
solucioneso incluso
fuente
Usando el
cut
comando:fuente
http
ydns
.Solo otra
grep
solución:Y uno similar con
sed
imprimir solo el grupo capturado coincidente:fuente
Otro
awk
enfoque:Eso establecerá el separador de campo de awk en uno
=
o en un espacio. Luego, si la línea coincide con a=
, entoncesud
otc
seguido de unp
, imprima el segundo campo.Otro
sed
enfoque (no portátil para todas las versiones desed
, pero funciona con GNUsed
):El
-n
medio "no imprime" y-E
permite expresiones regulares extendidas que nos dan\S
para "no espacios en blanco",+
para "uno o más" y los paréntesis para capturar. Finalmente, el/p
al final hará que sed imprima una línea solo si la operación fue exitosa, por lo que si hubo una coincidencia para el operador de sustitución.Y, uno perl:
El
-n
medio "lee el archivo de entrada línea por línea y aplica la secuencia de comandos dada por-e
a cada línea". El-l
añade una nueva línea para cadaprint
llamada (y elimina los saltos de línea que salen de la entrada). El script mismo imprimirá el tramo más largo de caracteres que no sean espacios en blanco encontrados después de aproto=
.fuente
-E
se está volviendo cada vez más portátil, pero\S
no lo es.[^[:space:]]
Es un equivalente más portátil.Aquí hay otra solución bastante fácil:
fuente
grep
no coincide con nada.[tc,ud]\*\\/.*
busca una aparición det
, oc
, o,
ou
od
, seguido de un*
carácter literal , luegop
ay una barra invertida. Probablemente quisiste decirgrep -Eo '(tc|ud)p/.* ' file | awk '{print $1}'
. Pero entonces, si estás usando awk, es posible que también lo haga la cosa entera en awk:awk -F'[= ]' '/(tc|ud)p/{print $2}' file
.[tc,ud]p
significa "uno det
,c
,,
,u
od
seguidas por unap
. Por lo tanto, los partidos aquí sólo porquetcp
tienecp
yudp
tienedp
. Pero también se correspondería,p
otp
etc. También, ahora que tiene el*
, que coincidiránppp
también (el*
medios "0 o más", por lo que coincidirá incluso cuando no coincide) usted no quiere una clase de caracteres (.[ ]
), lo que quiere es un grupo:(tc|ud)
(uso con la-E
bandera degrep
.) Además, la.*
hace coincidir con toda la línea.\*
para que el primero*
en su comando apareciera como un * y no como una marca de cursiva. Cuando pones el comando en formato de código, hiciste que apareciera el\
antes*
(lo que provocó que el comando fallara). Cuando edite las publicaciones de otras personas, tenga cuidado de cambiar la apariencia de la publicación de esta manera.ppp
. Por supuesto que tienes razón que coincidirá,p
otp
- ouucp
,ttp
,cutp
,ductp
od,up
.fuente
opciones de corte:
-f
- campo-d
- delimitadorfuente