我有两个文件,每个行按时间戳排序,但结构不同。我想合并文件信息一个文件和按时间戳排序。看起来像:
文件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
我该怎么做到这一点?有没有什么方法可以尽可能快地使它?
答案 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
这会连接两个文件,然后将时间戳放在行的开头。然后根据时间戳对其进行排序,然后删除该虚拟列。
虽然这对于大文件来说会很慢。