Trap Strg-C in awk-Skript

8

Ich glaube Ctrl- Ckann in Bash-Skripten gefangen sein. Ist es auch möglich, es in einem Awk-Skript abzufangen, um dieses Ereignis zu behandeln?

Zum Beispiel, um die Verarbeitung abzubrechen, aber die Ergebnisse dessen zu drucken, was bereits verarbeitet wurde, anstatt nur stillschweigend zu beenden?

Eugene Beresovsky
quelle
Sie müssen es in ein Shell-Skript einbinden oder eine Erweiterung für awk AFAIK schreiben.
Jai_s
1
Ja, lesen Sie zunächst
Folgendes
Ein Beispiel: github.com/takubo/awk-posix-signal
cuonglm

Antworten:

10

Mir ist keine awkImplementierung bekannt, die dies unterstützt. Sie könnten eine Erweiterung für schreiben gawkdafür , aber hier, würde ich eher in einer anderen Sprache wechseln.

perlmacht es einfach, awkSkripte mit seinem a2pSkript zu konvertieren .

Zum Beispiel, wenn Sie ein awkSkript haben wie:

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

a2p darauf gibt es dir so etwas wie:

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

Welche können Sie bearbeiten, um Ihre Signalbehandlung hinzuzufügen (und die Verarbeitung von var=valueArgumenten, die wir hier nicht wollen, und den Teil, der für Systeme gedacht ist, die nicht unterstützen, entfernen #!):

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

Eine weitere Alternative könnte sein , die zu unterbrechen Zuführung von Daten zu awkund hat awkdie SIGINT ignorieren, wie statt:

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

tun:

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

Ctrl+Cwird dann cataber nicht töten awk. awkDie verbleibende Eingabe wird weiterhin in der Pipe verarbeitet.

Um das Ctrl+CIn zu erkennen awk, können Sie Folgendes tun:

(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
quelle
Ich habe Ihr letztes Beispiel übernommen und es funktioniert großartig! Vielen Dank.
Eugene Beresovsky