awk: forçando um status de retorno?

17

Este é um seguimento da minha pergunta anterior .

Estou validando o número de campos em / etc / passwd usando este snippit útil. No exemplo a seguir, os usuários 'fieldcount1' e 'fieldcount2' têm o número errado 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 você notará, o awk sairá com um status de retorno igual a 0. Do ponto de vista dele, não há problemas aqui.

Gostaria de incorporar essa declaração do awk em um script de shell. Gostaria de imprimir todas as linhas com erro e definir o código de retorno como 1 (erro).

Posso tentar forçar um status de saída específico, mas o awk apenas imprime uma única linha:

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

Posso forçar o awk a sair com o status de retorno '1' e imprimir todas as linhas correspondentes?

Stefan Lasiewski
fonte

Respostas:

23

Mantenha o status em uma variável e use-o em um ENDbloco.

awk -F: 'NF != 7 {print; err = 1}
         END {exit err}' /etc/passwd
geekosaur
fonte
Muito bom. No entanto, estou tendo problemas para incorporar isso em um script bash. Estou tentando capturar o status de retorno dessa declaração do awk adicionando algo como ; echo $?depois dessa declaração do awk. No entanto, echo $?nunca é executado porque END {exit err}'finaliza o script. Existe uma maneira de definir o status de retorno sem sair?
Stefan Lasiewski
6
@StefanLasiewski exit errfinaliza o awk, não finaliza o script. Você tem set -enesse roteiro, por acaso? Nesse caso, você disse ao shell para sair se um comando retornar um status diferente de zero; se você quiser testar o status, use if awk …; then echo ok; else echo fail; fi.
Gilles 'SO- stop be evil'
@ Giles: Sim, este script foi set -edefinido. Isso explica o comportamento estranho que estou vendo. Obrigado por apontar isso.
Stefan Lasiewski
1
Se você planeja usar a saída com o &&operador do bash , vale lembrar que "0 é verdadeiro, mas falso é 1 no shell" .
Skippy le Grand Gourou
7

Eu estava procurando por algo semelhante ao grep, onde sairá 1 se uma correspondência não for encontrada. Aqui está o equivalente ao awk:

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

Exemplo

Steven Penny
fonte
0

Isso não responde aos requisitos exatos do OP, mas se você se preocupa apenas com o código de retorno e não precisa imprimir as linhas correspondentes, grep -qé possível modificar a resposta do @geekasaur para sair após a primeira correspondência, o que gera uma entrada enorme arquivos economizariam tempo se o erro ocorresse no início do arquivo. Espero /etc/passwdque não se qualifique para você!

awk -F: 'NF != 7 {err = 1; exit;}
     END {exit err}' /etc/passwd
Mark Stewart
fonte
1
awk -F: 'NF != 7 {exit 1}'fará o mesmo.
Stéphane Chazelas