Trap Ctrl-C no script awk

8

Eu acredito que Ctrl - C pode estar preso nos scripts bash. Também é possível prendê-lo dentro de um script Awk para lidar com esse evento?

Por exemplo, para interromper o processamento, mas imprimir os resultados do que já foi processado, em vez de simplesmente desistir?

    
por Eugene Beresovsky 09.02.2016 / 07:40

1 resposta

9

Não estou ciente de nenhuma implementação awk que tenha suporte para isso. Você poderia escrever uma extensão para gawk para isso , mas aqui, prefiro mudar para outro idioma.

perl facilita a conversão de awk scripts com seu script a2p .

Por exemplo, se você tiver um script awk como:

{count[$0]++}
END {
  for (i in count) printf "%5d %s\n", count[i], i
}

a2p vai lhe dar algo como:

#!/usr/bin/perl
eval 'exec /usr/bin/perl -S $0 ${1+"$@"}'
    if $running_under_some_shell;
                        # this emulates #! processing on NIH machines.
                        # (remove #! line above if indigestible)

eval '$'.$1.'$2;' while $ARGV[0] =~ /^([A-Za-z_0-9]+=)(.*)/ && shift;
                        # process any FOO=bar switches

while (<>) {
    chomp;      # strip record separator
    $count{$_}++;
}

foreach $i (keys %count) {
    printf "%5d %s\n", $count{$i}, $i;
}

Que você pode editar para adicionar seu tratamento de sinal (e remover o processamento de var=value argumentos que não queremos aqui, e a parte destinada a sistemas que não suportam #! ):

#!/usr/bin/perl

sub report {
  foreach $i (keys %count) {
      printf "%5d %s\n", $count{$i}, $i;
  }
}

$SIG{INT} = sub {
  print STDERR "Interrupted\n";
  report;
  $SIG{INT} = 'DEFAULT';
  kill('INT', $$); # report dying of SIGINT.
};

while (<>) {
    chomp;      # strip record separator
    $count{$_}++;
}

report;

Outra alternativa poderia ser interromper a alimentação de dados para awk e ter awk ignorando o SIGINT, como em vez de:

awk '{count[$0]++};END{for (i in count) printf "%5d %s\n", count[i], i}' file

faça:

cat file | (
  trap '' INT
  awk '{count[$0]++};END{for (i in count) printf "%5d %s\n", count[i], i}'
)

Ctrl + C irá então matar cat mas não awk . awk continuará processando a entrada restante ainda no pipe.

Para detectar o Ctrl + C em awk , você poderia fazer:

(cat file && echo cat terminated normally) | (
  trap '' INT
  awk '{count[$0]++}
       END{
         if ($0 == "cat terminated normally") delete count[$0]
         else print "Interrupted"
         for (i in count) printf "%5d %s\n", count[i], i}'
)
    
por 09.02.2016 / 13:14