Bẫy Ctrl-C trong tập lệnh awk


8

Tôi tin rằng Ctrl- Ccó thể bị mắc kẹt trong các tập lệnh bash. Có phải cũng có thể nhốt nó bên trong một tập lệnh Awk để xử lý sự kiện đó không?

Ví dụ, để hủy bỏ xử lý, nhưng in kết quả của những gì đã được xử lý, thay vì chỉ bỏ đi?


bạn sẽ phải gói nó trong một tập lệnh shell hoặc viết phần mở rộng cho awk AFAIK.
jai_s

1
Có, bắt đầu bằng cách đọc rằng: gnu.org/software/gawk/manual/html_node/ Kẻ
jlliagre

Câu trả lời:


10

Tôi không biết về bất kỳ awktriển khai nào có hỗ trợ cho việc đó. Bạn có thể viết một phần mở rộng cho gawkđiều đó , nhưng ở đây, tôi muốn chuyển sang ngôn ngữ khác.

perlgiúp dễ dàng chuyển đổi awkcác tập lệnh với a2ptập lệnh của nó .

Chẳng hạn, nếu bạn có một đoạn awkscript như:

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

a2p trên đó sẽ cung cấp cho bạn một cái gì đó như:

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

Bạn có thể chỉnh sửa để thêm xử lý tín hiệu của mình (và loại bỏ việc xử lý các var=valueđối số mà chúng tôi không muốn ở đây và phần dành cho các hệ thống không hỗ trợ #!):

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

Một cách khác có thể là làm gián đoạn việc cung cấp dữ liệu đến awkawkbỏ qua SIGINT, như thay vì:

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

làm:

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

Ctrl+Csau đó sẽ giết catnhưng không được awk. awkvẫn sẽ tiếp tục xử lý đầu vào còn lại vẫn còn trong đường ống.

Để phát hiện Ctrl+Ctrong awk, bạn có thể làm:

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

Tôi đã thông qua ví dụ cuối cùng của bạn và nó hoạt động rất tốt! Cảm ơn.
Eugene Beresovsky
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.