在没有首先对数据进行排序的情况下计算bash中唯一字符串的出现次数

时间:2016-01-29 23:57:04

标签: bash awk count

我正在收集大量日志文件的数据,我需要计算唯一字符串的出现次数。通常,这样做的方式是使用如下命令:

zcat <file> | grep -o <filter> | sort | uniq -c | sort -n

我要做的是不要在grep之后支付那种性能惩罚。这可能不用离开bash吗?

3 个答案:

答案 0 :(得分:3)

您可以使用awk计算唯一身份,并避免使用sort

zgrep -o <filter> <file> |
awk '{count[$0]++} END{for (i in count) print count[i], i}'

另请注意,您可以避免zcat并直接致电zgrep

答案 1 :(得分:1)

既然你提到你不想离开bash:你可以尝试使用关联数组:你可以使用输入行作为键,将计数作为值。要了解关联数组,请参阅此处:http://www.gnu.org/software/bash/manual/html_node/Arrays.html

但是,一定要对性能进行基准测试 - 尽管如此,使用sort和uniq,或者perl或者......可能会更好。

答案 2 :(得分:1)

jq有内置的关联数组,所以你可以考虑以下方法之一,它们都是有效的(比如awk):

zgrep -o <filter> <file> |
  jq -nR 'reduce inputs as $line ({}; .[$line] += 1)'

这将产生作为JSON对象的结果,其频率为对象的值,例如

{
  "a": 2,
  "b": 1,
  "c": 1
}

如果您希望每行输出都包含计数和值(按此顺序),那么适当的jq调用将是:

jq -nRr 'reduce inputs as $line ({}; .[$line] += 1)
         | to_entries[] | "\(.value) \(.key)"'

这会产生如下输出:

2 a
1 b
1 c

此处使用的jq选项为:

-n # for use with `inputs`
-R # "raw" input
-r # "raw" output