Acesso código de retorno do último comando no AWK

2

O comando não encontrado deve produzir o código de retorno 127 :

$ foo; echo $?
bash: foo: command not found...
127

Eu tentei atribuir $? à variável rc e depois imprimi-lo, mas RC é sempre 0 .

$ foo | awk -v rc="$?" 'BEGIN{print rc}'
0
bash: foo: command not found...

Descobriu que ele irá imprimir o RC correto apenas neste caso:

$ qazqaz
bash: qazqaz: command not found...
$ foo | awk -v rc="$?" 'BEGIN{print rc}'
127
bash: foo: command not found...

É possível trabalhar com RC no awk enquanto os tubos são usados? Ou o problema está em outro lugar?

Eu gostaria de me ater a algumas implementações portáteis do awk.

    
por A.D. 06.11.2017 / 16:41

2 respostas

4

Em um pipeline, os comandos são executados simultaneamente. Esse é o ponto principal, a saída de um é alimentada para o outro em tempo real.

Você só sabe o status de saída de um comando quando ele retorna. Se você quiser que awk processe a saída de foo e também obtenha acesso ao status de saída, será necessário executar awk após foo após ter armazenado foo ' s saída em algum lugar como:

foo > file
awk -v "rc=$?" '{print rc, $0}' < file

Como alternativa, você pode ter awk run foo (bem, ainda através de um shell para interpretar uma linha de comando), ler sua saída (através de um pipe através de sua interface cmd | getline para popen() ) e obtenha seu status de saída com:

awk -v cmd=foo '
  BEGIN {
    while ((cmd | getline) > 0) {
      print
    }
    rc = close(cmd)
    print rc
  }'

No entanto, observe que o modo awk codifica o status de saída varia de uma implementação de awk para a próxima. Em alguns, o status é reto, como retornado por waitpid() ou pclose() , em outros é aquele dividido por 256 (mesmo quando foo é eliminado por um sinal) ... embora você deva contar com rc sendo 0 se e somente se o comando foi bem sucedido.

No caso de gawk , mudou recentemente .

Ou você pode ter o status de saída alimentado no final pelo canal:

(foo; echo "$?") | awk '
   {saved = $0}
   NR > 1 {
     # process the previous line
     $0 = prev
     print "output:", $0
   }
   {prev = saved}
   END{rc = prev; print rc}'

(assumindo que a saída de foo termine em um caractere de nova linha quando não estiver vazia (é um texto válido)).

Ou alimentado por um tubo separado. Por exemplo, no Linux e com um shell diferente de ksh93:

{ : extra pipe | { (foo 3<&-; echo "$?" > /dev/fd/3) | awk '
  {print}
  END {getline rc < "/dev/fd/3"; print rc}'
} 3<&0 <&4 4<&-; } 4<&0
    
por 06.11.2017 / 17:25
0

Use o comando type e assim:

type test > /dev/null 2>&1
echo $?
0

type fsfsf > /dev/null 2>&1
echo $?
1
    
por 06.11.2017 / 16:59