连接两个匹配两列且不匹配的文件,并在每个匹配行中,将文件 1 中的第二列替换为文件 2 中的第六列

连接两个匹配两列且不匹配的文件,并在每个匹配行中,将文件 1 中的第二列替换为文件 2 中的第六列

我正在努力完成这项任务:

我有两个文件:
文件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 fromfile1 into the arraya`。

  • 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并确保有来自file1in 的所有钥匙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

相关内容