Perangkap Ctrl-C dalam skrip awk

8

Saya percaya Ctrl- Cdapat terjebak dalam skrip bash. Apakah mungkin untuk menjebaknya di dalam skrip Awk untuk menangani peristiwa itu?

Misalnya, untuk membatalkan pemrosesan, tetapi mencetak hasil dari apa yang sudah diproses, bukan hanya berhenti secara diam-diam?

Eugene Beresovsky
sumber
Anda harus membungkusnya dalam skrip shell atau menulis ekstensi untuk awk AFAIK.
jai_s
1
Ya, mulailah dengan membaca bahwa: gnu.org/software/gawk/manual/html_node/…
jlliagre

Jawaban:

10

Saya tidak mengetahui adanya awkimplementasi yang memiliki dukungan untuk itu. Anda dapat menulis ekstensi untuk gawkitu , tetapi di sini, saya lebih suka beralih ke bahasa lain.

perlmembuatnya mudah untuk mengkonversi awkskrip dengan a2pskripnya.

Misalnya, jika Anda memiliki awkskrip seperti:

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

a2p di atasnya akan memberi Anda sesuatu seperti:

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

Yang dapat Anda edit untuk menambahkan penanganan sinyal Anda (dan menghapus pemrosesan var=valueargumen yang tidak kita inginkan di sini, dan bagian yang ditujukan untuk sistem yang tidak mendukung #!):

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

Alternatif lain bisa untuk mengganggu makan data ke awk, dan memiliki awkmengabaikan SIGINT itu, seperti bukan:

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

melakukan:

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

Ctrl+Ckemudian akan membunuh cattetapi tidak awk. awkakan tetap memproses sisa input yang masih dalam pipa.

Untuk mendeteksi Ctrl+Cdalam awk, Anda bisa melakukan:

(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
sumber
Saya mengadopsi contoh terakhir Anda dan itu berhasil! Terima kasih.
Eugene Beresovsky