Я считаю, что 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}' )