多个大文件排序

时间:2017-02-23 08:30:39

标签: shell sorting unix awk

我有两个文件,每个行按时间戳排序,但结构不同。我想合并文件信息一个文件和按时间戳排序。看起来像:

文件A(小于2G)

1,1,1487779199850
2,2,1487779199852
3,3,1487779199854
4,4,1487779199856
5,5,1487779199858

文件B(小于15G)

1,1,10,100,1487779199850
2,2,20,200,1487779199852
3,3,30,300,1487779199854
4,4,40,400,1487779199856
5,5,50,500,1487779199858

我该怎么做到这一点?有没有什么方法可以尽可能快地使它?

2 个答案:

答案 0 :(得分:1)

$ awk -F, -v OFS='\t' '{print $NF, $0}' fileA fileB | sort -s -n -k1,1 | cut -f2-
1,1,1487779199850
1,1,10,100,1487779199850
2,2,1487779199852
2,2,20,200,1487779199852
3,3,1487779199854
3,3,30,300,1487779199854
4,4,1487779199856
4,4,40,400,1487779199856
5,5,1487779199858
5,5,50,500,1487779199858

我最初发布的内容仅仅是@VM17's answer下的评论,但他建议我将其作为新答案。

上面会更加健壮和高效,因为它使用sort + cut(tab)的默认分隔符,真正只对第一个键进行排序(尽管它会使用整行-k1因为sort字段分隔符选项卡不在行中,所以使用稳定的排序算法(sort -s)来保留输入顺序并使用cut去除添加的关键字段比再次调用awk更有效,因为awk会在每条记录上进行字段拆分等,而不需要删除前导字段。

另外,你可能会发现这样的效率更高:

$ cat tst.awk
{ currRec = $0; currKey = $NF }
NR>1 {
    print prevRec
    printf "%s", saved
    while ( (getline < "fileB") > 0 ) {
        if ($NF < currKey) {
            print
        }
        else {
            saved = $0 ORS
            break
        }
    }
}
{ prevRec = currRec; prevKey = currKey }
END {
    print prevRec
    printf "%s", saved
    while ( (getline < "fileB") > 0 ) {
        print
    }
}

$ awk -f tst.awk fileA
1,1,1487779199850
1,1,10,100,1487779199850
2,2,1487779199852
2,2,20,200,1487779199852
3,3,1487779199854
3,3,30,300,1487779199854
4,4,1487779199856
4,4,40,400,1487779199856
5,5,1487779199858
5,5,50,500,1487779199858

正如您所看到的,它从文件B读取行文件A之间的比较时间戳,因此它交错了2个文件,因此不需要后续管道进行排序和剪切。

只是检查一下逻辑,因为我没有多想,并且要注意这是一种罕见的情况,其中getline可能适合效率,但请务必阅读http://awk.freeshell.org/AllAboutGetline以了解所有注意事项如果你我一直在考虑再次使用它。

答案 1 :(得分:0)

试试这个 -

awk -F, '{print $NF, $0}' fileA fileB | sort -nk 1 | awk '{print $2}'

输出 -

1,1,10,100,1487779199850
1,1,1487779199850
2,2,1487779199852
2,2,20,200,1487779199852
3,3,1487779199854
3,3,30,300,1487779199854
4,4,1487779199856
4,4,40,400,1487779199856
5,5,1487779199858
5,5,50,500,1487779199858

这会连接两个文件,然后将时间戳放在行的开头。然后根据时间戳对其进行排序,然后删除该虚拟列。

虽然这对于大文件来说会很慢。