awk/sed/grep删除与另一个文件中的字段匹配的行

tri*_*id3 6 linux bash awk sed

我有一个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
Run Code Online (Sandbox Code Playgroud)

文件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
Run Code Online (Sandbox Code Playgroud)

......(以及500,000行)

所以在这种情况下,我想删除file1的第四行(就地).

以下是我要删除的行:

grep "$(awk '{print $3,$4,$5}' file1)" file2
Run Code Online (Sandbox Code Playgroud)

因此,一种解决方案可能是将其传输到sed,但我不清楚如何在sed中设置匹配模式来自管道输入.在网上搜索建议awk可能会完成所有这些(或者也许是sed或其他东西),所以想知道什么是干净的解决方案.

此外,速度有点重要,因为其他进程可能会尝试修改文件(我知道这可能会带来更多的复杂性......).匹配通常位于file2的末尾,而不是开头(如果有一些方法可以从下往上搜索file2).

Ed *_*ton 5

$ 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
Run Code Online (Sandbox Code Playgroud)

file2 包含 500,000 行的事实对于 awk wrt 内存或执行速度应该没有问题 - 即使在最坏的情况下它也应该在大约 1 秒或更短的时间内完成。

使用任何 UNIX 命令,要覆盖您只需执行的原始文件:

cmd file > tmp && mv tmp file
Run Code Online (Sandbox Code Playgroud)

所以在这种情况下:

awk '...' file2 file1 > tmp && mv tmp file1
Run Code Online (Sandbox Code Playgroud)