Usar múltiples delimitadores en awk

202

Tengo un archivo que contiene las siguientes líneas:

/logs/tc0001/tomcat/tomcat7.1/conf/catalina.properties:app.env.server.name = demo.example.com
/logs/tc0001/tomcat/tomcat7.2/conf/catalina.properties:app.env.server.name = quest.example.com
/logs/tc0001/tomcat/tomcat7.5/conf/catalina.properties:app.env.server.name = www.example.com

En la salida anterior, quiero extraer 3 campos (Número 2, 4 y el último *.example.com). Estoy obteniendo el siguiente resultado:

cat file | awk -F'/' '{print $3 "\t" $5}'
tc0001   tomcat7.1
tc0001   tomcat7.2
tc0001   tomcat7.5

¿Cómo extraigo también el último campo con el nombre de dominio que está después '='? ¿Cómo uso multiple delimiterpara extraer el campo?

Satish
fuente
2
Para responder a mi pregunta, que es la misma pero diferente, awkera tragar campos cuando estaban en blanco, lo que impedía la numeración de campos. He cambiado -F " "a -F "[ ]"y awkno tragó los campos vacíos más.
Adam

Respuestas:

324

El delimitador puede ser una expresión regular.

awk -F'[/=]' '{print $3 "\t" $5 "\t" $8}' file

Produce:

tc0001   tomcat7.1    demo.example.com  
tc0001   tomcat7.2    quest.example.com  
tc0001   tomcat7.5    www.example.com
Embedded.kyle
fuente
42
Por supuesto, catno se requiere proceso: awk '...' file. Además, sería más ordenado usar el separador de campo de salida:awk -F'[/=]' -v OFS="\t" '{print $3, $5, $8}'
Glenn Jackman
17
Los delimitadores Awk pueden ser expresiones regulares ... ¡esto me alegró el día!
das.cyklone
44
@ das.cyklone: ​​awk también puede tener varios separadores, con |: ej: awk -F 'this|that|[=/]' '......' (útil para tener palabras / cadenas que separan cosas) (tenga en cuenta que esto mantiene los espacios en los campos entre 2 separadores. Agregar también |[ \t]+puede ser útil, pero puede hacer cosas complicado ... como a menudo hay espacios antes y después de 'this', esto hará que aparezcan 2 campos vacíos adicionales entre los espacios y 'this')
Olivier Dulac
He intentado esto en 2 distribuciones diferentes y obtengo el mismo comportamiento: quiero obtener el puerto de netstat -ntpl "netstat -ntpl | sed 's /: / /' | awk '{print $ 5}'" funciona pero podría funcionar sin tubería doulbe Esto funciona pero no esperaba los datos en el campo 17: "netstat -ntpl | awk -F" |: "'{print $ 17}'"
louigi600
2
sí ... esto me consiguió lo que quería: awk -F "[:] +" '/ \ / postmaster * $ / {print $ 5}'
louigi600
44

¡Buenas noticias! awkEl separador de campo puede ser una expresión regular. Solo necesitas usar -F"<separator1>|<separator2>|...":

awk -F"/|=" -vOFS='\t' '{print $3, $5, $NF}' file

Devoluciones:

tc0001  tomcat7.1  demo.example.com
tc0001  tomcat7.2  quest.example.com
tc0001  tomcat7.5  www.example.com

Aquí:

  • -F"/|="establece el separador de campo de entrada en /o =. Luego, establece el separador de campo de salida en una pestaña.

  • -vOFS='\t'está usando la -vbandera para establecer una variable. OFSes la variable predeterminada para el Separador de campo de salida y se establece en el carácter de tabulación. La bandera es necesaria porque no hay incorporado para el OFS como -F.

  • {print $3, $5, $NF} imprime los campos tercero, quinto y último en función del separador de campo de entrada.


Ver otro ejemplo:

$ cat file
hello#how_are_you
i#am_very#well_thank#you

Este archivo tiene dos campos separadores, #y _. Si queremos imprimir el segundo campo, independientemente de que el separador sea uno u otro, ¡hagamos que ambos sean separadores!

$ awk -F"#|_" '{print $2}' file
how
am

Donde los archivos están numerados de la siguiente manera:

hello#how_are_you           i#am_very#well_thank#you
^^^^^ ^^^ ^^^ ^^^           ^ ^^ ^^^^ ^^^^ ^^^^^ ^^^
  1    2   3   4            1  2   3    4    5    6
fedorqui 'así que deja de dañar'
fuente
1
Gracias @BUFU por tu edición. Eliminé la referencia OFS para centrarme solo en la parte FS, pero también es bueno tenerla. ¡Salud!
Fedorqui 'SO deja de dañar'
5

Si su espacio en blanco es consistente, puede usarlo como un delimitador, también en lugar de insertarlo \tdirectamente, puede configurar el separador de salida y se incluirá automáticamente:

< file awk -v OFS='\t' -v FS='[/ ]' '{print $3, $5, $NF}'
Thor
fuente
3

Para un separador de campo de cualquier número a 2través de una 5letra ao #un espacio, donde el carácter de separación debe repetirse al menos 2 veces y no más de 6 veces, por ejemplo:

awk -F'[2-5a# ]{2,6}' ...

Estoy seguro de que existen variaciones de esto usando () y parámetros

genoma
fuente
3

Perl one-liner:

perl -F'/[\/=]/' -lane 'print "$F[2]\t$F[4]\t$F[7]"' file

Se utilizan estas opciones de línea de comandos:

  • -nrecorra cada línea del archivo de entrada, coloque la línea en la $_variable, no imprima automáticamente cada línea

  • -l elimina las nuevas líneas antes del procesamiento y las agrega nuevamente

  • -amodo de división automática: Perl dividirá automáticamente las líneas de entrada en la @Fmatriz. Por defecto se divide en espacios en blanco

  • -Fmodificador de división automática, en este ejemplo se divide en cualquiera /o=

  • -e ejecuta el código perl

Perl está estrechamente relacionado con awk, sin embargo, la @Fmatriz de división automática comienza en el índice, $F[0]mientras que los campos awk comienzan con $ 1.

Chris Koknat
fuente
2

Otra es usar la opción -F pero pasarla regex para imprimir el texto entre paréntesis izquierdo y derecho ().

El contenido del archivo:

528(smbw)
529(smbt)
530(smbn)
10115(smbs)

El comando:

awk -F"[()]" '{print $2}' filename

resultado:

smbw
smbt
smbn
smbs

Usando awk para imprimir el texto entre []:

Úselo awk -F'[][]' pero awk -F'[[]]'no funcionará.

http://stanlo45.blogspot.com/2020/06/awk-multiple-field-separators.html

Stan Lovisa
fuente
Su respuesta apareció en la cola de eliminación porque 9 de cada 10 veces, los usuarios con 1 reputación que vinculan a su propio blog generalmente son spam. Pero el tuyo es la excepción a la regla. En los últimos 10 años de contenido hay una mina de oro, ojalá tengas un plan para inmortalizarla.
Eric Leschinski
0

Veo que hay muchas respuestas perfectas en la pizarra, pero también me gustaría subir mi código,

awk -F"/" '{print $3 " " $5 " " $7}' sam | sed 's/ cat.* =//g'

Sadhun
fuente
2
print $3 " " $5 " " $7se puede imprimir igual que print $3, $5, $7. Además, no veo la ventaja de usar awk y luego canalizar para sed. En general, awk puede ser suficiente y otras respuestas muestran eso.
fedorqui 'SO deja de dañar'