Trap Ctrl-C nello script awk


8

Credo Ctrl- Cpuò essere intrappolato negli script bash. È anche possibile intrappolarlo all'interno di uno script Awk per gestire quell'evento?

Ad esempio, per interrompere l'elaborazione, ma stampare i risultati di ciò che è già stato elaborato, invece di smettere di fumare?


dovrai avvolgerlo in uno script di shell o scrivere un'estensione per awk AFAIK.
jai_s,


Risposte:


10

Non sono a conoscenza di alcuna awkimplementazione che supporti tale. Potresti scrivere un'estensione per gawkquesto , ma qui, preferirei passare a un'altra lingua.

perlsemplifica la conversione di awkscript con il suo a2pscript.

Ad esempio, se hai uno awkscript come:

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

a2p su di esso ti darà qualcosa di simile:

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

Che puoi modificare per aggiungere la tua gestione del segnale (e rimuovere quell'elaborazione degli var=valueargomenti che non vogliamo qui e la parte destinata ai sistemi che non supportano #!):

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

Un'altra alternativa potrebbe essere quella di interrompere l' alimentazione dei dati a awk, e hanno awkignorare il SIGINT, come invece di:

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

fare:

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

Ctrl+Cpoi ucciderà catma non awk. awkcontinuerà a elaborare l'input rimanente ancora nella pipe.

Per rilevare l' Ctrl+Cin awk, si potrebbe fare:

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

Ho adottato il tuo esempio finale e funziona benissimo! Grazie.
Eugene Beresovsky,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.