awk: ¿forzar un estado de devolución?

17

Este es un seguimiento de mi pregunta anterior .

Estoy validando el número de campos en / etc / passwd usando este práctico fragmento de código. En el siguiente ejemplo, los usuarios 'fieldcount1' y 'fieldcount2' tienen el número incorrecto de campos:

$ awk -F: ' NF!=7 {print}' /etc/passwd
fieldcount1:x:1000:100:fieldcount1:/home/fieldcount1:/bin/bash::::
fieldcount2:blah::blah:1002:100:fieldcount2:/home/fieldcount2:/bin/bash:
$ echo $?
0

Como notará, awk saldrá con un estado de retorno de 0. Desde su punto de vista, aquí no hay problemas.

Me gustaría incorporar esta declaración awk en un script de shell. Me gustaría imprimir todas las líneas que son error, y establecer el código de retorno en 1 (error).

Puedo intentar forzar un estado de salida particular, pero luego awk solo imprime una sola línea:

$ awk -F: ' NF!=7 {print ; exit 1}' /etc/passwd
fieldcount1:x:1000:100:fieldcount1:/home/fieldcount1:/bin/bash::::
$ echo $?
1

¿Puedo forzar a awk a salir con un estado de retorno de '1' e imprimir todas las líneas que coincidan?

Stefan Lasiewski
fuente

Respuestas:

23

Mantenga el estado en una variable y úselo en un ENDbloque.

awk -F: 'NF != 7 {print; err = 1}
         END {exit err}' /etc/passwd
geekosaur
fuente
Muy bien. Sin embargo, me encuentro con problemas al incorporar esto en un script bash. Estoy tratando de capturar el estado de retorno de esta declaración awk agregando algo como ; echo $?después de esta declaración awk. Sin embargo, echo $?nunca se ejecuta porque END {exit err}'termina el script. ¿Hay alguna manera de establecer el estado de devolución sin salir?
Stefan Lasiewski
66
@StefanLasiewski exit errtermina awk, no termina el script. ¿Tienes set -een ese guión, por casualidad? Si es así, le ha dicho al shell que salga si un comando devuelve un estado distinto de cero; si desea probar el estado, use if awk …; then echo ok; else echo fail; fi.
Gilles 'SO- deja de ser malvado'
@Giles: Sí, este script se ha set -econfigurado. Eso explica el extraño comportamiento que estoy viendo. Gracias por señalar eso.
Stefan Lasiewski
1
Si planea usar la salida con el &&operador de bash , vale la pena tener en cuenta que "0 es verdadero pero falso es 1 en el shell" .
Skippy le Grand Gourou
7

Estaba buscando algo similar a grep, donde saldrá 1 si no se encuentra una coincidencia. Aquí está el equivalente con awk:

awk '
BEGIN   {z=1}
/bravo/ {z=0; print}
END     {exit z}
' alpha.txt

Ejemplo

Steven Penny
fuente
0

Esto no responde a los requisitos exactos de OP, pero si solo le importa el código de retorno y no necesita imprimir las líneas que coinciden, similar a grep -q, entonces puede modificar la respuesta de @geekasaur para salir después de la primera coincidencia, lo que para una gran entrada los archivos ahorrarían tiempo si el error es temprano en el archivo. ¡Ojalá /etc/passwdno califique para ti!

awk -F: 'NF != 7 {err = 1; exit;}
     END {exit err}' /etc/passwd
Mark Stewart
fuente
1
awk -F: 'NF != 7 {exit 1}'Hará lo mismo.
Stéphane Chazelas