Captura Ctrl-C en script awk

8

Creo que Ctrl- Cpuede ser atrapado en scripts bash. ¿También es posible atraparlo dentro de un script Awk para manejar ese evento?

Por ejemplo, para abortar el procesamiento, pero imprimir los resultados de lo que ya se ha procesado, en lugar de simplemente dejarlo en silencio.

Eugene Beresovsky
fuente
tendrá que envolverlo en un script de shell o escribir una extensión para awk AFAIK.
jai_s
1
Sí, comience leyendo eso: gnu.org/software/gawk/manual/html_node/…
jlliagre

Respuestas:

10

No conozco ninguna awkimplementación que tenga soporte para eso. Podrías escribir una extensión para gawkeso , pero aquí, prefiero cambiar a otro idioma.

perlfacilita la conversión de awkscripts con su a2pscript.

Por ejemplo, si tiene un awkscript como:

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

a2p en ella te 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 puede editar para agregar su manejo de señal (y eliminar ese procesamiento de var=valueargumentos que no queremos aquí, y la parte destinada a sistemas que no son compatibles #!):

#!/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;

Otra alternativa podría ser la de interrumpir la alimentación de los datos a awk, y tienen awkignorar la SIGINT, al igual que en lugar de:

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

hacer:

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

Ctrl+Centonces matará catpero no awk. awkseguirá procesando la entrada restante en la tubería.

Para detectar la Ctrl+Cen awk, usted podría hacer:

(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
fuente
¡Adopté tu ejemplo final y funciona muy bien! Gracias.
Eugene Beresovsky