我正在努力完成这项任务:
我有两个文件:
文件1好像:
102 13.342
103 7.456
105 6.453
107 3.567
108 4.210
文件2好像:
0 098 0 0 0 -9 x
0 099 0 0 0 -9 x
0 100 0 0 0 -9 x
0 101 0 0 0 -9 x
0 102 0 0 0 -9 x
0 103 0 0 0 -9 x
0 104 0 0 0 -9 x
0 105 0 0 0 -9 x
0 106 0 0 0 -9 x
0 106 0 0 0 -9 x
0 107 0 0 0 -9 x
0 108 0 0 0 -9 x
我想要一个文件3看起来像
0 098 0 0 0 -9 x
0 099 0 0 0 -9 x
0 100 0 0 0 -9 x
0 101 0 0 0 -9 x
0 102 0 0 0 13.342 x
0 103 0 0 0 7.456 x
0 104 0 0 0 -9 x
0 105 0 0 0 6.453 x
基本上,我想通过分别匹配 file1 和 file2 中的第一个和第二个字段来连接 file1 和 file2,保持不匹配,并且在每个匹配行中用 file1 中第二个字段的值替换 file2 中第六个字段的值。 ..
我知道这个任务与使用有关:
join -a1 -a2 -o 1.2 whatsoever
。但无法弄清楚如何继续...还考虑 awk
答案1
当涉及的领域如此之多时,我倾向于选择awk
:
$ awk 'NR==FNR{a[$1]=$2; next}{if($2 in a){$6=a[$2]}}1;' file1 file2
0 098 0 0 0 -9 x
0 099 0 0 0 -9 x
0 100 0 0 0 -9 x
0 101 0 0 0 -9 x
0 102 0 0 0 13.342 x
0 103 0 0 0 7.456 x
0 104 0 0 0 -9 x
0 105 0 0 0 6.453 x
0 106 0 0 0 -9 x
0 106 0 0 0 -9 x
0 107 0 0 0 3.567 x
0 108 0 0 0 4.210 x
解释
NR==FNR{a[$1]=$2; next}
:NR
是当前行号,FNR
是当前文件的当前行号。当处理多个文件时,只有在读取第一个文件时,两个文件才会相等。a[$1]=$2
使用st field as a key to an array whose value is the 2nd field. The
下一个skips to the next line. So, this will save all values from
file1into the array
a`。if($2 in a){$6=a[$2]}
:现在我们正在读取第二个文件。如果该行的第二个字段存在于数组中a
,则将第 6 个字段 ( ) 设置为第二个字段$6
中存储的内容。a
1;
:这是“打印这一行”的简写。
答案2
如果两个文件都按键字段排序(通常是第 6 个字段-9
)
join -1 2 -a 1 -e '-9' -o 1.1 1.2 1.3 1.4 1.5 2.2 1.7 file2 file1
完成这项工作(感谢钢铁起子用于修正)
但更正确的是sed`s 格式:
join -1 2 -a 1 2 1 -o 1.1,1.2,1.3,1.4,1.5,1.6,2.2,1.7 |
sed 's/ \S*\( \S\+\)/\1/3'
如果你更喜欢awk并确保有来自file1
in 的所有钥匙file2
awk '{
a=0
do {
if (a)
print a
getline a <"file2"
split(a,A)
}
while($1 != A[2])
i=0
A[6]=$2
for(i in A)
printf("%s ",A[i++])
print ""
}' file1