对大型数据文件进行排序和求和

时间:2013-11-07 09:47:13

标签: sorting awk uniq

我必须处理sort似乎无法处理的文件。 这些文件是apprx。每个3 GB。

输入如下:

last-j  nmod+j+n    year-n 9492
last-j  nmod+j+n    night-n 8075
first-j nmod+j+n-the    time-n 7749
same-j  nmod+j+n-the    time-n 7530
other-j nmod+j+n-the    hand-n 5319
ast-j   nmod+j+n   year-n 1000
last-j   nmod+j+n   night-n 5000
first-j   nmod+j+n-the   time-n 1000
same-j   nmod+j+n-the   time-n 3000
other-j   nmod+j+n-the   hand-n 200

我需要在其中总结相应副本的数量。

所以期望的输出如下:

   last-j   nmod+j+n    year-n 10492
    last-j  nmod+j+n    night-n 13075
    first-j nmod+j+n-the    time-n 8749
    same-j  nmod+j+n-the    time-n 10530
    other-j nmod+j+n-the    hand-n 5519

我一直在尝试这种排序命令,应该可以解决这个问题

sort input | uniq -c | awk '{print $2 "\t" $3 "\t" $1*$4}' 

并且内存不足。有什么建议可能会更优化处理更大的数据文件?感谢

3 个答案:

答案 0 :(得分:2)

awk中使用数组,您可以一起完成所有操作,无需sortuniq

$ awk '{a[$1,$2,$3]+=$4} END{for (i in a) print i, a[i]}' file
first-jnmod+j+n-thetime-n 8749
ast-jnmod+j+nyear-n 1000
same-jnmod+j+n-thetime-n 10530
last-jnmod+j+nnight-n 13075
last-jnmod+j+nyear-n 9492
other-jnmod+j+n-thehand-n 5519

由于这是使用第1列,第2列,第3列作为索引,因此它们一起写入。这可以通过另一个数组来解决:

$ awk '{a[$1,$2,$3]+=$4; b[$1,$2,$3]=$1" "$2" "$3} END{for (i in a) print b[i], a[i]}' a
first-j nmod+j+n-the time-n 8749
ast-j nmod+j+n year-n 1000
same-j nmod+j+n-the time-n 10530
last-j nmod+j+n night-n 13075
last-j nmod+j+n year-n 9492
other-j nmod+j+n-the hand-n 5519

答案 1 :(得分:2)

sort和其他纯粹神奇的UNIX工具一样优化 - 可能 - 可以。如果您正在计算文件中的条目,并且它们的唯一事件不适合内存,则将它们加载到内存中将不是一个好的解决方案 - 这是最快的方法,否则。

除此之外,排序文件 - O(n log n) - 以及稍后对条目进行排序 - O(n) - 肯定是最佳解决方案 - 除非您保留{{1} - 内存中条目的大小映射,并且每当k键尝试添加到映射时,继续将数据从mem交换到磁盘。考虑到这一点,您的解决方案(带有k + 1的单行)只需要点击一下。

使用sort + uniq + awk的神奇能力尝试外部sort文件;在此之后,计数将最多需要一个条目保存在内存中 - 这几乎可以解决您的问题。最终的双线可能是这样的:

sort

答案 2 :(得分:1)

如果内存不足,那是因为sortuniqawk只占用了不变的内存量。您可以与GNU parallel并行运行多个排序,例如:来自手册:

cat bigfile | parallel --pipe --files sort | parallel -Xj1 sort -m {} ';' rm {} >bigfile.sort
  

这里bigfile被分成大约1MB的块,每个块以...结尾   '\ n'(这是--recend的默认值)。每个块都被传递给sort   并且sort的输出保存到文件中。传递这些文件   到第二个在它之前的文件上运行sort -m的并行   删除文件。输出保存到bigfile.sort。

文件排序后,您可以通过您正在使用的uniq / awk管道进行流式处理,例如:

cat bigfile.sort | uniq -c | awk '{print $2 "\t" $3 "\t" $1*$4}'