Piège Ctrl-C dans le script awk

8

Je crois Ctrl- Cpeut être piégé dans des scripts bash. Est-il également possible de le piéger dans un script Awk afin de gérer cet événement?

Par exemple, pour abandonner le traitement, mais imprimer les résultats de ce qui a déjà été traité, au lieu de simplement cesser de fumer?

Eugene Beresovsky
la source
vous devrez l'envelopper dans un script shell ou écrire une extension pour awk AFAIK.
jai_s
1
Oui, commencez par lire cela: gnu.org/software/gawk/manual/html_node/…
jlliagre

Réponses:

10

Je ne connais aucune awkimplémentation qui prend en charge cela. Vous pouvez écrire une extension pour gawkcela , mais ici, je préfère passer à une autre langue.

perlfacilite la conversion de awkscripts avec son a2pscript.

Par exemple, si vous avez un awkscript comme:

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

a2p dessus vous donnera quelque chose comme:

#!/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 vous pouvez modifier pour ajouter votre gestion du signal (et supprimer ce traitement d' var=valuearguments dont nous ne voulons pas ici, et la partie destinée aux systèmes qui ne prennent pas en charge #!):

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

Une autre alternative pourrait être d'interrompre l' alimentation des données à awk, et ont awkignorer le SIGINT, comme au lieu de:

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

faire:

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

Ctrl+Cva alors tuer catmais pas awk. awkcontinuera à traiter l'entrée restante toujours dans le tuyau.

Pour détecter l' Ctrl+Cen awk, vous pouvez le faire:

(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
la source
J'ai adopté votre dernier exemple et ça marche très bien! Merci.
Eugene Beresovsky