【问题标题】:Finding a uniq -c substitute for big files寻找 uniq -c 替代大文件
【发布时间】:2015-09-02 22:22:25
【问题描述】:

我有一个大文件 (50 GB),我想计算其中不同行出现的次数。通常我会使用

sort bigfile | uniq -c

但文件足够大,排序需要大量的时间和内存。我可以的

grep -cfx 'one possible line'

对于文件中的每个唯一行,但这意味着 n 会为每个可能的行遍历文件,这(虽然对内存更友好)比原来的要花费更长的时间。

有什么想法吗?


A related question 询问一种在大文件中查找唯一行的方法,但我正在寻找一种方法来计算每个行的实例数-- 我已经知道可能的线路是什么了。

【问题讨论】:

标签: bash shell uniq gnu-toolchain linux-toolchain


【解决方案1】:

使用awk

awk '{c[$0]++} END {for (line in c) print c[line], line}' bigfile.txt

这在时间上是 O(n),在空间上是 O(unique lines)。

【讨论】:

  • 可以说,这填充了我的 bash 版本中的“将此逻辑移植到 awk”请求。 :)
  • bigfile.txt 可以是 awk 命令参数,不需要输入重定向。
【解决方案2】:

这是使用jq 1.5 的解决方案。它与 awk 解决方案在方法和性能特征上基本相同,但输出是表示哈希的 JSON 对象。 (可以对程序进行简单的修改以产生另一种格式的输出。)

调用:

$ jq -nR 'reduce inputs as $line ({}; .[$line] += 1)' bigfile.txt

如果 bigfile.txt 包含以下几行:

a
a
b
a
c

那么输出将是:

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

【讨论】:

    【解决方案3】:
    #!/bin/bash
    # port this logic to awk or ksh93 to make it fast
    
    declare -A counts=( )
    while IFS= read -r line; do
      counts[$line]=$(( counts[$line] + 1 )) # increment counter
    done
    
    # print results
    for key in "${!counts[@]}"; do
      count=${counts[$key]}
      echo "Found $count instances of $key"
    done
    

    【讨论】:

    • grep 有什么帮助,它将匹配所有行?
    • @Barmar,它只匹配已知集中的行。当我阅读这个问题时,这些都散布在 OP 不关心的其他行中。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-10
    • 1970-01-01
    • 1970-01-01
    • 2015-06-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多