Ловушка Ctrl-C в awk-скрипте

Я считаю, что Ctrl- C может быть захвачен сценариями bash. Возможно ли также уловить его внутри сценария Awk для обработки этого события?

Например, для прерывания обработки, но распечатывая результаты уже обработанного, вместо того, чтобы просто замолчать?

Я не знаю о какой-либо реализации awk , которая поддерживает это. Вы могли бы написать расширение для gawk для этого , но здесь я предпочел бы перейти на другой язык.

perl упрощает преобразование awk скриптов с a2p скрипта a2p .

Например, если у вас есть awk скрипт, например:

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

a2p на нем даст вам что-то вроде:

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

Что вы можете редактировать, чтобы добавить обработку сигнала (и удалить эту обработку аргументов var=value которые мы здесь не хотим, и часть, предназначенная для систем, которые не поддерживают #! ):

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

Другой альтернативой может быть прерывание подачи данных на awk и awk игнорировать SIGINT, например, вместо:

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

делать:

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

Ctrl + C будет убивать cat но не awk . awk все равно будет продолжать обрабатывать оставшийся вход в трубке.

Чтобы обнаружить Ctrl + C в awk , вы можете сделать следующее:

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