最初の列の一致する値に基づいてファイル列の値を置き換えます。

最初の列の一致する値に基づいてファイル列の値を置き換えます。

質問があります。アッ最初の列の値が一致すると、file1 の 2 つの列の値の一部を 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

問題には2つの側面があります。

  • まず、入力フィールド区切り文字をに設定し、,入力をスペースで区切るように宣言します。これにより、現場作業が正しく機能しなくなります。入力がスペースで区切られている場合、入力行はデフォルトで「スペース」(つまり直接連続するスペースとタブの数)に分割されるため、実際にFS設定する必要はありません。awk
  • 2番目の問題はあなたの状況にありますif (a[$1])。現在の行の最初の列の値file1が上にある場合、これは正確ですが、コードは実際に希望の値をfile2変更するのではなく、変更されていない行を印刷します。file1file2
  • 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

関連情報