我有一个file1,有几行(十行)和一个更长的file2(~500,000行)。尽管存在相同的字段子集,但每个文件中的行不相同。我想从file1中的每一行获取字段3-5,并搜索file2以获得相同的模式(只有这三个字段,按相同的顺序 - 在file2中,它们属于字段2-4)。如果找到任何匹配项,那么我想从file1中删除相应的行。
例如,file1:
2016-01-06T05:38:31 2016-01-06T05:23:33 2016006 120E A TM Current
2016-01-06T07:34:01 2016-01-06T07:01:51 2016006 090E B TM Current
2016-01-06T07:40:44 2016-01-06T07:40:41 2016006 080E A TM Alt
2016-01-06T07:53:50 2016-01-06T07:52:14 2016006 090E A TM Current
2016-01-06T08:14:45 2016-01-06T08:06:33 2016006 080E C TM Current
file2的:
2016-01-06T07:35:06.87 2016003 100E C NN Current 0
2016-01-06T07:35:09.97 2016003 100E B TM Current 6303
2016-01-06T07:36:23.12 2016004 030N C TM Current 0
2016-01-06T07:37:57.36 2016006 090E A TM Current 399
2016-01-06T07:40:29.61 2016006 010N C TM Current 0
......(以及500,000行)
所以在这种情况下,我想删除file1的第四行(就地)。
以下找到我要删除的行:
grep "$(awk '{print $3,$4,$5}' file1)" file2
所以一个解决方案可能是把它传递给sed,但我不清楚如何在sed中设置匹配模式来自管道输入。在网上搜索建议awk可能会完成所有这些(或者也许是sed或其他东西),所以想知道什么是干净的解决方案。
此外,速度有点重要,因为其他进程可能会在此过程中尝试修改文件(我知道这可能会带来更多复杂性......)。匹配通常位于file2的末尾,而不是开头(如果有从头到尾搜索file2的方法)。
答案 0 :(得分:4)
$ awk 'NR==FNR{file2[$2,$3,$4]; next} !(($3,$4,$5) in file2)' file2 file1
2016-01-06T05:38:31 2016-01-06T05:23:33 2016006 120E A TM Current
2016-01-06T07:34:01 2016-01-06T07:01:51 2016006 090E B TM Current
2016-01-06T07:40:44 2016-01-06T07:40:41 2016006 080E A TM Alt
2016-01-06T08:14:45 2016-01-06T08:06:33 2016006 080E C TM Current
file2包含500,000行的事实对于awk wrt内存或执行速度应该没问题 - 即使在最坏的情况下也应该在大约1秒或更短的时间内完成。
使用任何UNIX命令,只需覆盖原始文件:
cmd file > tmp && mv tmp file
所以在这种情况下:
awk '...' file2 file1 > tmp && mv tmp file1
答案 1 :(得分:1)
您可以在file1
中找到不匹配的行:
$ grep -v -F -f <(awk '{ print $3,$4,$5 }' file2) file1
2016-01-06T05:38:31 2016-01-06T05:23:33 2016006 120E A TM Current
2016-01-06T07:34:01 2016-01-06T07:01:51 2016006 090E B TM Current
2016-01-06T07:40:44 2016-01-06T07:40:41 2016006 080E A TM Alt
2016-01-06T08:14:45 2016-01-06T08:06:33 2016006 080E C TM Current
只需将其重定向到某处,然后覆盖file1
。