awk / sed / grep删除与其他文件中的字段匹配的字段

我有一个文件1,有几行(几十),和一个更长的文件2(约50万行)。 每个文件中的行不相同,尽pipe有一些相同的字段的子集。 我想从file1中的每行取3-5字段,并searchfile2中相同的模式(只是这三个字段,顺序相同 – 在file2中,它们落在字段2-4中)。 如果find任何匹配,那么我想从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 

文件2:

 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的第四行(in place)。

以下find我想要删除的行:

 grep "$(awk '{print $3,$4,$5}' file1)" file2 

所以一个解决scheme可能是pipe这个sed,但我不清楚如何设置匹配模式在pipe道inputsed。 在线search表明,awk可能会做所有这些(或者也许是sed或其他),所以想知道干净的解决scheme是什么样的。

另外,速度有点重要,因为其他进程可能会尝试修改这些文件(我知道这可能会带来更多的复杂性)。 匹配通常会在file2的结尾find,而不是从头开始(如果有某种方法可以从下往上searchfile2)。

 $ 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行应该是没有问题的内存或执行速度 – 即使在最坏的情况下,它应该完成大约1秒或更少。

使用任何UNIX命令,可以覆盖原来的文件:

 cmd file > tmp && mv tmp file 

所以在这种情况下:

 awk '...' file2 file1 > tmp && mv tmp file1 

您可以在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