Bash

uniq 行的實時計數

  • May 12, 2020

我有一個命令可以不斷輸出幾條不同的行(一個流),我想要一個實時總結每行發生的次數(可以接受幾秒鐘的延遲)。

例如,如果我的命令輸出以下內容:

apple
apple
apple
apple
banana
orange
banana

我想要類似的東西:

4 apple
2 banana
1 orange

並讓輸出每隔幾秒刷新一次。

我怎樣才能做到這一點?(重新讀取整個日誌文件會花費很長時間,它必須是實時管道的輸出)

你可以使用 awk:

... | awk '{seen[$0]++} !(NR % 10) {print "======"; for (i in seen) print seen[i], i}'

這將保持重複計數 ( seen[$0]++),並每十個輸入行列印一次 ( !(NR % 10))。例如:

% % while sleep 1; do echo $((RANDOM % 10)); done | awk '{seen[$0]++} !(NR % 10) {print "======"; for (i in seen) print seen[i], i}'
======
1 0
1 1
3 3
1 6
2 7
2 9
======
3 0
3 1
1 2
3 3
1 4
2 5
2 6
3 7
2 9
======
3 0
3 1
2 2
3 3
2 4
5 5
4 6
3 7
2 8
3 9
...

可以用一個簡短的perl腳本來完成,例如:

#! /usr/bin/perl
system qw(tput sc); # save cursor
$rc = `tput rc; tput ed`; # restore cursor and erase down
sub report {
 print $rc;
 print "$_: $c{$_}\n" for sort {
   ($c{$b} <=> $c{$a}) || ($a cmp $b)
 } keys %c;
 STDOUT->flush;
 alarm 1;
}
$SIG{ALRM} = \&report;
alarm 1;
while (<>) {
 chomp;
 $c{$_}++;
}
report;

引用自:https://unix.stackexchange.com/questions/586060