Bash脚本:计算文件中的唯一行


129

情况:

我有一个大文件(数百万行),其中包含来自几个小时网络捕获的IP地址和端口,每行一个ip /端口。行的格式如下:

ip.ad.dre.ss[:port]

所需结果:

我在记录日志时收到的每个数据包都有一个条目,因此有很多重复的地址。我希望能够通过某种shell脚本运行该脚本,从而可以将其简化为以下格式的行

ip.ad.dre.ss[:port] count

其中count,该特定地址(和端口)的出现次数。无需执行任何特殊工作,将不同的端口视为不同的地址。

到目前为止,我正在使用此命令从日志文件中抓取所有IP地址:

grep -o -E [0-9]+\.[0-9]+\.[0-9]+\.[0-9]+(:[0-9]+)? ip_traffic-1.log > ips.txt

由此,我可以使用一个相当简单的正则表达式来抓取我的地址发送的所有IP地址(我不在乎)

然后,我可以使用以下内容提取唯一条目:

sort -u ips.txt > intermediate.txt

我不知道如何以某种方式汇总行数。

Answers:


303

您可以使用以下uniq命令来获取重复行的计数:

sort ips.txt | uniq -c

为了获得最常见的结果(感谢Peter Jaric):

sort ips.txt | uniq -c | sort -bgr

10
我喜欢-bgr巧合地看起来像的助记符bigger,这就是我们想要的顶部。
dwanderson '18

1
作为您.bashrc.bash_aliases文件的一项小功能:function countuniquelines () { sort "$1" | uniq -c | sort -bgr; }。致电countuniquelines myfile.txt
约翰

不知道为什么不sort -nr
Nakilon

5

计算唯一行的总数(即不考虑重复行),我们可以使用uniq或Awk与wc

sort ips.txt | uniq | wc -l
awk '!seen[$0]++' ips.txt | wc -l

Awk的数组是关联数组,因此它的运行速度可能比排序快。

生成文本文件:

$  for i in {1..100000}; do echo $RANDOM; done > random.txt
$ time sort random.txt | uniq | wc -l
31175

real    0m1.193s
user    0m0.701s
sys     0m0.388s

$ time awk '!seen[$0]++' random.txt | wc -l
31175

real    0m0.675s
user    0m0.108s
sys     0m0.171s

有趣。可能会对庞大的数据集产生明显的影响
Wug

1

这是获得重复行数并以最不频繁到最频繁的方式将它们很好地打印出来的最快方法:

awk '{!seen[$0]++}END{for (i in seen) print seen[i], i}' ips.txt | sort -n

如果您不关心性能,并且想要更容易记住,则只需运行:

sort ips.txt | uniq -c | sort -n

PS:

sort -n将字段解析为数字,这是正确的,因为我们正在使用计数进行排序。


!{!seen[$0]++}是多余的在这里,因为我们只做印刷的END
阿米尔
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.