Intercepte Ctrl-C no script awk

8

Eu acredito Ctrl- Cpode ser preso em scripts bash. Também é possível prendê-lo dentro de um script do 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 sair silenciosamente?

Eugene Beresovsky
fonte
você precisará envolvê-lo em um script de shell ou escrever uma extensão no awk AFAIK.
jai_s
1
Sim, comece lendo o seguinte: gnu.org/software/gawk/manual/html_node/…
jlliagre

Respostas:

10

Não conheço nenhuma awkimplementação que tenha suporte para isso. Você poderia escrever uma extensão para gawkisso , mas aqui, prefiro mudar para outro idioma.

perlfacilita a conversão de awkscripts com seu a2pscript.

Por exemplo, se você tiver um awkscript como:

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

a2p nele 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=valueargumentos 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 pode ser a interromper a alimentação de dados para awk, e têm awkignorar o SIGINT, como em vez de:

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

Faz:

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

Ctrl+Centão matará catmas não awk. awkainda continuará processando a entrada restante ainda no tubo.

Para detectar a Ctrl+Cno 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}'
)
Stéphane Chazelas
fonte
Adotei o seu exemplo final e funciona muito bem! Obrigado.
Eugene Beresovsky