我想合并两个文件(一个是空格分隔的,另一个是分隔符),只保留两个文件之间匹配的记录:
文件1:空格分隔
A B C D E F G H
s e id_234 4 t 5 7 9
r d id_45 6 h 3 9 10
f w id_56 2 y 7 3 0
s f id_67 2 y 10 3 0
文件2:制表符分隔
I L M N O P
s e 4 u id_67 88
d a 5 d id_33 67
g r 1 o id_45 89
我想将文件1字段3(“C”)与文件2字段5(“O”)匹配,并合并这样的文件:
文件3:制表符分隔
I L M N O P A B D E F G H
s e 4 u id_67 88 s f 2 y 10 3 0
g r 1 o id_45 89 r d 6 h 3 9 10
文件1中的条目没有出现在文件2中,反之亦然,但我只想保留交集(公共ID)。
我并不关心订单。
我宁愿不使用join,因为这些是非常大的未排序文件,并且join需要先按公共字段排序,这需要很长时间和很多内存。
我尝试使用awk但未成功
awk > file3 'NR == FNR {
f2[$3] = $2; next
}
$5 in f2 {
print $0, f2[$2]
}' file2 file1
有人可以帮帮我吗?
非常感谢
答案 0 :(得分:2)
嗯..理想情况下,你应该避免使用基于awk的方法所需的n ^ 2解决方案。对于file1中的每个记录,您必须扫描file2以查看是否发生。这就是时间的流逝。
我建议为此编写一个python(或类似)脚本,并为其中一个文件构建一个map id->文件位置,然后在扫描另一个文件时查询该文件。这会让你成为一个nlogn运行时,至少对我来说,这看起来是你在这里做的最好的(使用索引的哈希会让你遇到寻找文件pos的昂贵问题)。
事实上,这是Python脚本:
f1 = file("file1.txt")
f1_index = {}
# Generate index for file1
fpos = f1.tell()
line = f1.readline()
while line:
id = line.split()[2]
f1_index[id] = fpos
fpos = f1.tell()
line = f1.readline()
# Now scan file2 and output matches
f2 = file("file2.txt")
line = f2.readline()
while line:
id = line.split()[4]
if id in f1_index:
# Found a matching line, seek to file1 pos and read
# the line back in
f1.seek(f1_index[id], 0)
line2 = f1.readline().split()
del line2[2] # <- Remove the redundant id_XX
new_line = "\t".join(line.strip().split() + line2)
print new_line
line = f2.readline()
答案 1 :(得分:0)
如果对这两个文件进行排序(在你想要匹配的列上)是一种可能性(并且不会以某种方式破坏内容),join
可能是一个更好的方法,而不是试图用{{ 1}}或bash
。既然你说你不关心顺序,那么这可能是一个合适的方法。
它看起来像这样:
加入-1 3 -2 5 -o'2.1,2.2,2.3,2.4,2.5,2.6,1.1,1.2,1.4,1.5,1.6,1.7,1.8'&lt;(sort -k3,3 file1)&lt ;(sort -k5,5 file2)
我希望有更好的方法告诉它输出哪些列,因为这是很多输入,但这就是它的工作方式。您也可以放弃awk
内容,然后使用-o ...
或其他内容对输出进行后期处理,以使其符合您想要的顺序......