根据第一列的匹配值替换文件列中的值

根据第一列的匹配值替换文件列中的值

我有一个问题awk当第一列中的值匹配时,将 file1 中两列中的某些值替换为 file2 中的值。

这是一个例子:

我有:

  • file1
    
    A 2012 3
    B 2012 4
    C 2012 9
    D 2012
    E 2012 7
    F 2012 
    
  • file2
    
    D 2007 12
    F 2009 8 
    G 2000 4
    

所需的输出是当第 1 列中的值匹配时我希望将第 2 列和第 3 列中的值替换为 file2 中的值,如下所示:

  • 期望的输出:
    
    A  2012  3 
    B  2012  4  
    C  2012  9 
    D  2007  12
    E  2012  7  
    F  2009  8  
    

我使用了这段代码,我知道它有问题

 awk 'BEGIN{FS=",";OFS="\t"}
    FNR==NR{a[$1]=$2;b[$1]=$3; next}
    FNR>=1{if(a[$1]){print $0 }else{print $1, a[$1], b[$1] }}
    ' file2 file1

因为当我使用这段代码时,我获得的输出是:

A  2012  3 
B  2012  4  
C  2012  9 
D  2012    
E  2012  7  
F  2012     

这与 相同file1

有人可以向我解释这段代码有什么问题或建议替代解决方案吗?

答案1

问题有两个方面。

  • 首先,您将输入字段分隔符设置为,,而您声明输入是空格分隔的。那么,您的任何现场操作都将无法正常进行。如果输入是空格分隔的,则实际上FS根本不需要设置,因为awk默认情况下会在“空白”处分割输入行(即任意数量的直接连续的空格和制表符)。
  • 第二个问题在于你的状况if (a[$1])。如果当前行的第一列值file1也存在于 中file2,则这是正确的,但在您的代码中,您将打印 中 未更改的行,而不是替换您实际想要的file1中 的值。file2
  • 此外,您使用print $0打印输入行,其字段分隔符与从 读取的字段分隔符相同file1,从而忽略OFS="\t"这些行的指令。

相反,请使用以下内容:

awk 'BEGIN{OFS="\t"}
     NR==FNR{col2[$1]=$2;col3[$1]=$3;next}
     FNR>=1{if ($1 in col2) {$2=col2[$1];$3=col3[$1]} else {$1=$1}}1' file2 file1

$1=$1强制awk使用实际的输出字段分隔符重新构建行,以便空格正确地替换为\t

相关内容