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?


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}'
)

J'ai adopté votre dernier exemple et ça marche très bien! Merci.
Eugene Beresovsky
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.