我有两个文件如下:
文件1
"Connect" CONNECT_ID="12"
"Connect" CONNECT_ID="11"
"Connect" CONNECT_ID="122"
"Connect" CONNECT_ID="109"
file2的
"Quit" CONNECT_ID="12"
"Quit" CONNECT_ID="11"
文件内容不完全相同,但与上述类似,记录数最少为100,000。
现在我想将结果如下所示显示在 file1 中(表示最终结果应该在file1中)
"Connect" CONNECT_ID="122"
"Connect" CONNECT_ID="109"
我使用了类似下面的while循环:
awk {'print $2'} file2 | sed "s/CONNECTION_ID=//g" > sample.txt
while read actual; do
grep -w -v $actual file1 > file1_tmp
mv -f file1_tmp file1
done < sample.txt
这里我根据示例调整了我的代码。所以它可能也可能不起作用。
我的问题是循环重复超过1小时才能完成整个过程。
所以任何人都可以建议我如何使用diff
或comm
或sed
或awk
或任何其他linux命令来实现相同的目标跑得快?
这里主要是我要消除这个典型的while
循环。
答案 0 :(得分:6)
大多数UNIX工具都是基于行的,因为您没有整行匹配,这意味着grep
,comm
和diff
不在窗口。要提取您想要的基于字段的信息awk
是完美的:
$ awk 'NR==FNR{a[$2];next}!($2 in a)' file2 file1
"Connect" CONNECT_ID="122"
"Connect" CONNECT_ID="109"
要将结果存储回file1
,您需要将输出重定向到临时文件,然后将文件移动到file1
,如下所示:
$ awk 'NR==FNR{a[$2];next}!($2 in a)' file2 file1 > tmp && mv tmp file1
<强>解释强>
awk
变量NR
为每个读取的记录递增,即每个文件中的每一行。每个记录的FNR
变量递增,但每个文件都会重置。
NR==FNR # This condition is only true when reading file1
a[$2] # Add the second field in file1 into array as a lookup table
next # Get the next line in file1 (skips any following blocks)
!($2 in a) # We are now looking at file2 if the second field not in the look up
# array execute the default block i.e print the line
要修改此命令,您只需更改匹配的字段即可。在您的实际情况下,如果您想将file1
中的字段1与file2
中的字段4匹配,那么您可以这样做:
$ awk 'NR==FNR{a[$1];next}!($4 in a)' file2 file1
答案 1 :(得分:4)
这可能适合你(GNU sed):
sed -r 's|\S+\s+(\S+)|/\1/d|' file2 | sed -f - -i file1
答案 2 :(得分:2)
最适合这项工作的工具是join(1)
。它根据每个文件的给定列中的值连接两个文件。通常它只输出两个文件中匹配的行,但它也有一个模式来输出与其他文件不匹配的文件中的行。
join
要求在您加入的字段上对文件进行排序,因此要么对文件进行预排序,要么使用进程替换(bash
功能 - 如示例中所示在一个命令行上执行此操作:
$ join -j 2 -v 1 -o "1.1 1.2" <(sort -k2,2 file1) <(sort -k2,2 file2)
"Connect" CONNECT_ID="122"
"Connect" CONNECT_ID="109"
-j 2
表示加入两个文件的第二个字段上的文件。
-v 1
表示仅输出文件1中与文件2中的任何内容不匹配的字段
-o "1.1 1.2"
表示要使用文件1的第一个字段(1.1
)和文件1的第二个字段(1.2
)对输出进行排序。如果没有这个,join
将首先输出连接列,然后输出其余列。
答案 3 :(得分:0)
您可能需要一键分析file2,并附加所有已经出现在缓存中的ID(例如内存) 比逐行扫描file1来调整缓存中的ID。
像这样的python代码:#!/usr/bin/python
# -*- coding: utf-8 -*-
import re
p = re.compile(r'CONNECT_ID="(.*)"')
quit_ids = set([])
for line in open('file2'):
m = p.search(line)
if m:
quit_ids.add(m.group(1))
output = open('output_file', 'w')
for line in open('file1'):
m = p.search(line)
if m and m.group(1) not in quit_ids:
output.write(line)
output.close()
答案 4 :(得分:0)
主要的瓶颈不是while
循环,而是你重写输出文件数千次。
在您的特定情况下,您可能只能这样做:
cut -f2 file2 | grep -Fwvf - file1 >tmp
mv tmp file1
(我不认为-w
的{{1}}选项在这里很有用,但是因为你在你的例子中有它,我保留了它。)
这预先假定grep
以制表符分隔;如果没有,那你file2
就好了。