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

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

以下のようにfileA.txtがあります。

title              trial_exp  values
Version            1.0
Blank1                        0.010
Blank2                        0.200
Blank3                        0.100
Test_field_Asia               1.500
Test_field_Europe             0.900
Test_field_America            2.000

次に、次のようなfileB.txtがあります。

Test_field_Asia     Thailand
Test_field_Europe   UK
Test_field_America  Mexico

fileAの列1のすべての名前をfileBの列1の名前と一致させ、一致するものが見つかった場合は列2の値を変更しようとします。

希望の出力:

title               trial_exp   values
Version             1.0
Blank1                          0.010
Blank2                          0.200
Blank3                          0.100
Test_field_Asia     Thailand    1.500
Test_field_Europe   UK          0.900
Test_field_America  Mexico      2.000

次のコードを試しました。

awk 'NR==FNR{rec[$1]=$2;next}{temp=$1} temp in rec{$2=rec[temp]}1' fileA.txt fileB.txt

ただし、交換は完了しておらず、元のfileA.txtが印刷されました。

誰かがこのコードの問題を説明したり、代替ソリューションを提案したりできますか?

答え1

これは解決策

  1. ファイルの作成myscript.sh
#!/bin/bash
awk 'BEGIN{FS=",";OFS="\t"}
    FNR==NR{myfile2[$1]=$2; next}
    FNR>1{if(myfile2[$1]){print $1, myfile2[$1], $3,NR}else{print $1,$2,$3}}
' fileB.txt fileA.txt
  1. 実行してください:
chmod +x myscript.sh
./myscript.sh

次のような出力が得られます。

Version 1.0 
Blank1      0.010
Blank2      0.200
Blank3      0.100
Test_field_Asia Thailand    1.500   9
Test_field_Europe   UK  0.900   10
Test_field_America  Mexico  2.000   11
  1. 出力でカンマを区切り文字として使用するには、変更できます。OFS="," 次の出力が表示されます。
Version,1.0,
Blank1,,0.010
Blank2,,0.200
Blank3,,0.100
Test_field_Asia,Thailand,1.500,9
Test_field_Europe,UK,0.900,10
Test_field_America,Mexico,2.000,11
  1. 任意に選択できる。fileA.txtタイトル(最初の行)を含めたい場合ㅏ)簡単に条件を変更できます。FNR>=1または雨)スクリプトを簡単に書き直してください。
#!/bin/bash
awk 'BEGIN{FS=",";OFS="\t"}
    FNR==NR{myfile2[$1]=$2; next}
    myfile2[$1]{print $1, myfile2[$1], $3; next;}{print $1,$2,$3}
' fileB.txt fileA.txt

最後に、詳細な例については、以下をお読みください。 https://www.baeldung.com/linux/awk-multiple-input-files

答え2

あなたが望むのは本質的にデータベース接続です。これを行うための適切な名前のコマンドがありますjoin。問題は、ソートされた入力が必要であることです。行の順序が関連しない場合は、次のことができます。

join -a1 <(sort fileA.txt) <(sort fileB.txt)

-a1オプションは、マージできない行を印刷します。 2 つの <(...) 構成は、 sort コマンドの出力を含む一時ファイルを生成します。あなたの例を使用すると、結果は次のようになります。

Blank1 0.010
Blank2 0.200
Blank3 0.100
Test_field_America 2.000 Mexico
Test_field_Asia 1.500 Thailand
Test_field_Europe 0.900 UK
title trial_exp values
Version 1.0

(例をコピーしてタブを空白に変更したことに気づきました。)

これタイトルそしてバージョン行はヘッダーである可能性があるため、いくつかの後処理が必要です。

関連情報