編集する

編集する

列がタブで区切られた異なる形式の2つのファイルがあります。の列をとcolumn1比較する必要があります。一致する場合は、の値をの値に置き換える必要があります。試してみましたが、値を置き換えることはできません。以下のコードスニペットの提案を提供できますか?column2file1file2column6file1column3file2awk

awk 'FILENAME == ARGV[1] {
    m[$1,$2] = $6;
    next;
}
{
    if (($1,$2) in m) {
        m[$6]= $3; print m[$6];
    }
}' file1 file2


top few lines of file1
1201 12011 1 0 0 0 1
1202 12021 1 0 0 0 1
1203 12031 1 0 0 0 1
1204 12041 1 0 0 0 2
1207 12071 1 0 0 0 2
1209 12091 1 0 0 0 1
1210 12101 1 0 0 0 1
1212 12121 1 0 0 0 1
1213 12131 1 0 0 0 1
1214 12141 1 0 0 0 2

top few lines of file2
1201    12011   1
1202    12021   1
1203    12031   1
1204    12041   1
1206    NA  1
1207    12071   2
1208    NA  1
1209    12091   2
1210    12101   2

更新された内容を別のファイルに書きたいので、file2の値をfile1列に割り当てたいと思います。out.txt

編集する

コメントに基づいて次のコードを試しました。

awk '{
    if (FNR==NR) {
        a[FNR]=$1;b[FNR]=$2;c[FNR]=$3}
    else {             
        if (a[FNR] == $1 && b[FNR] ==$2) {
            $6=c[FNR]} else {$6=$6};
           print $0;
        }
    }' file2 file1

この出力を得る

1201 12011 1 0 0 1 1
1202 12021 1 0 0 1 1
1203 12031 1 0 0 1 1
1204 12041 1 0 0 1 2
1207 12071 1 0 0 0 2
1209 12091 1 0 0 0 1
1210 12101 1 0 0 0 1
1212 12121 1 0 0 0 1
1213 12131 1 0 0 0 1
1214 12141 1 0 0 0 2

答え1

awk -F"\t" -v OFS="\t" '{
    if (FNR==NR) {
        a[FNR]=$1;b[FNR]=$2;c[FNR]=$3}
    else {
        if (a[FNR] == $1 && b[FNR] ==$2) {
            $6=c[FNR]} else {$6=$6};
            print $0
        }
    }' file2 file1

私はこれが仕事を終えると思います。まず、それぞれインデックスを使用して、file2の最初、2番目、および3番目の列をarrayに格納しますa(file2の行のみ)。 Else (file1 の行のみに適用) 配列 sum の値を sum と比較します。一致する場合は、配列の6番目のフィールドを変更します。それ以外の場合は、値を同じ値に再割り当てし、区切り文字を 。bcFNRFNR = NRab$1$2ctab

答え2

大きなハンマーではなく別のawkアプローチ

while read f1 f2 f3; do 
    sed -E -i "s/^($f1\s+$f2.*)([0-9]+)$/\1$f3/" file1;
done < file2 

最後の数字が整数であると仮定します。そうでない場合は、([0-9])$適切なキャプチャグループに変更する必要があります。

これは file1 の内部変更に依存するため、コピーが必要です。

答え3

awkスクリプトを見ると、各入力ファイルを異なる方法で処理する正しいアイデアが既にあります(ほとんどの場合、NR == FNR数値比較が文字列比較よりも速いため、よりよく高速に動作することを確認しますが... ...何千もの入力がある場合)これが重要です(1つまたは2つのファイルの入力行数)。

ただし、スクリプトが目的の操作を実行できないようにするいくつかの問題があります。

  1. 間違った順序でファイルを読み込んでいます。 file1の行を出力して6列をfile2の列3に置き換えようとするので、まずfile2を読み込んで配列を作成する必要がありますm(file2のインデックス、file2の$1,$2値)。$3

  2. 修正m[$6]後に印刷しています。最大1つの列が印刷されます。

次のようにしてみてください。

$ awk 'NR == FNR    { m[$1,$2] = $3; next }
       ($1,$2) in m { $6 = m[$1,$2] }
       1' file2 file1
1201 12011 1 0 0 1 1
1202 12021 1 0 0 1 1
1203 12031 1 0 0 1 1
1204 12041 1 0 0 1 2
1207 12071 1 0 0 2 2
1209 12091 1 0 0 2 1
1210 12101 1 0 0 2 1
1212 12121 1 0 0 0 1
1213 12131 1 0 0 0 1
1214 12141 1 0 0 0 2

またはNR == FNR最初の行を元のFILENAME == ARGV[1]

各行file2(読み取る最初のファイル - コマンドラインのファイル名引数の順序に注意してください)ごとに$ 3を配列に保存し、m次の入力行にジャンプします。列の合計は、配列へのインデックス$1として使用されます。$2

その後、読み取りfile1(および後続の入力ファイルがある場合)が配列のインデックスである場合は、配列に格納されている値に($1,$2)置き換えられます。$6m

次に、変更の有無にかかわらず、現在の入力行を印刷します(モード自体は、「現在の1入力行の印刷」を意味するawkイディオム/ショートカットです。「1」はtrueと評価され、デフォルトのジョブは「印刷」です。だから事実上「真なら印刷されます」)

注:サンプルの予想出力を提供していないため、出力が必要なものと一致していることを確認できません。通常、OPのサンプル出力をファイルに保存し、鉱山が一致するかどうかを使用または確認するのが好きdiffですcmp。私のawkスクリプトの出力が一致します。私の説明あなたの質問で何を求めていますか?

関連情報