好的,所以我有两个文件:
file1.txt
object1 4598 -3.32 0 XxXxXx
object2 5987 -1.98 0 XxXxXx
object3 4529 -3.01 1 AbXxXx
object4 6134 -2.81 0 XxXxXx
object5 5912 -2.12 0 XxXxXx
object6 4529 -3.01 1 TeXxXx
object7 4529 -3.01 1 LoXxXx
object8 6915 -2.64 0 XxXxXx
...
和
file2.txt
object2 5987 -1.98 1 AnXxXx
object4 6134 -2.81 1 ChXxXx
object8 6915 -2.64 1 SnXxXx
对于两个文件中存在的给定对象,唯一的区别在于第4列和第5列。我想使用file1.txt
上提供的信息更新file2.txt
。我想要的输出是:
object1 4598 -3.32 0 XxXxXx
object2 5987 -1.98 1 AnXxXx
object3 4529 -3.01 1 AbXxXx
object4 6134 -2.81 1 ChXxXx
object5 5912 -2.12 0 XxXxXx
object6 4529 -3.01 1 TeXxXx
object7 4529 -3.01 1 LoXxXx
object8 6915 -2.64 1 SnXxXx
我能够使用for
中的bash
循环和grep
编写解决方案,合并两个文件,grep
基于file1的对象名称,然后做tail -1
以获得正确的行。 真的丑陋(见下文)并且处理时间太长(file1.txt有4700行),但它确实给了我想要的输出。
#!/bin/bash
for k in $(awk '{print $1}' file1.txt)
do
grep -w $k <(cat file1.txt file2.txt | sort) | tail -1 >> updated_file1.txt
done
请注意,我(危险地)依赖于sort
基于字段4对事物进行排序的事实,因为1-3是相同的。我承认这里有很多可能出错......
我想知道是否有人可以帮我找到更快的解决方案,例如,不需要查看整个文件。提前谢谢!
答案 0 :(得分:4)
awk
救援!
$ awk ' {k=$1 FS $2 FS $3} # set the key
NR==FNR {a[k]=$0; next} # cache the first file's rows by key
k in a {$0=a[k]}1' file2 file1 # if key from the second file in cache replace
object1 4598 -3.32 0 XxXxXx
object2 5987 -1.98 1 AnXxXx
object3 4529 -3.01 1 AbXxXx
object4 6134 -2.81 1 ChXxXx
object5 5912 -2.12 0 XxXxXx
object6 4529 -3.01 1 TeXxXx
object7 4529 -3.01 1 LoXxXx
object8 6915 -2.64 1 SnXxXx
这假设前三个字段需要匹配,否则将密钥更改为前一个或前两个字段而不更改其余代码。
答案 1 :(得分:1)
有趣的管道
join -a1 -j1 -o 0,1.2,1.3,2.4,2.5,1.4,1.5 <(sort file1.txt) <(sort file2.txt) |
tr -s '[:blank:]' |
cut -d' ' -f 1-5