awk配列の解釈?

awk配列の解釈?

私は初めてawkプログラミングに触れ、配列の仕組みを学んでいます。このコードが見つかりました。

awk 'BEGIN{OFS=FS=","}NR==FNR{a[$1]=$2;next}$3 in a && $3 = a[$3]' filez filex

それらは$1それを配列のインデックスとして置き、インデックスと同じ場合は$2値に入れます。最初のファイルには2つの列しかないので、これが何を意味するのか理解できません。 2番目のファイルと比較してどこから来たのですか? ! ?$3$3 = a[$3]$3$3

入力ファイルfilez:

111,111
112,114
113,113

入力ファイルfilex:

A,bb,111,xxx,nnn
A,cc,112,yyy,nnn
A,dd,113,zzz,ppp

答え1

このスクリプトの目的は、2番目のファイル()の3番目の列の値を1番目のファイルfilex()の2番目の列に格納されている値に置き換えることですfilez

NR処理された最初のファイルの最初の行に基づいて現在の行の行番号。 「グローバル」ラインカウンター。FNR現在処理中のファイルの先頭に基づく現在行番号。
NR==FNR最初のファイルに対してのみ真と評価される条件です。対応する操作({a[$1]=$2;next})は、最初のファイル全体を1行ずつ辞書に入れます。辞書は、a最初の列の対応する値に基づいて最初のファイルの2番目の列の値を見つけることを目的とした連想配列です。残りの条件をnextスキップしてawkループを再開し、次の行を読みます。

$3 in a && $3 = a[$3]潜在的な副作用がある条件(割り当て済み)です$3。 2番目のファイルのみが評価されます(NR==FNRfalseの場合、NR==FNRtrueの場合は$3 in a && $3 = a[$3]スキップされます)。各行に対して、3番目のフィールド(インデックス)の値がDictionaryで見つかった場合は、aそれを辞書の対応する値に置き換えます。そして$3 = a[$3]、評価結果が真であれば該当ラインが出力される(AWKプログラムでは基本的に条件(または「パターン」)-アクションペアで構成されるため、条件やアクションのいずれかを省略でき、省略されたアクションは同じであるprint)。

これが短縮されたとしますfilez

111,111
112,114

そしてfilex

A,bb,111,xxx,nnn
A,cc,112,yyy,nnn

段階的に起こるものは次のとおりです。

  1. filez最初の行はtrueNR==FNRと評価されます1==1。したがって、{a[$1]=$2;next}実行はスクリプトの残りの部分をスキップすることを意味しますa[111](特に現在は使用されていません)。111next$3 in a && $3 = a[$3]$3

  2. filez2番目と最後の行はNR==FNRと評価され、2==2再び何も印刷されないために設定されます。{a[$1]=$2;next}a[112]114$3 in a && $3 = a[$3]next

  3. filex最初の行を読むと、falseNR==FNRと評価されます。3==1{a[$1]=$2;next}いいえ次の条件付き:$3はの111インデックス値aなのでtrue$3 in aで評価されます$3 = a[$3]。結果は空の文字列ではないため、条件付き割り当てもtrueと評価され、現在の行が印刷されます。a[111]111$31110

    A,bb,111,xxx,nnn
    
  4. filex2番目と最後の行を読み取ると、falseNR==FNRと評価されます。4==2{a[$1]=$2;next}いいえ次の条件付き: と は のインデックス値なので true なので評価されます。結果は空の文字列ではない$3ため、条件付き割り当てもtrueと評価され、現在の行が印刷されます。112a$3 in a$3 = a[$3]a[112]114$31140

    A,cc,114,yyy,nnn
    

答え2

  • BEGIN{OFS=FS=","}入力フィールドと出力フィールドの区切り記号をに設定します,
  • NR==FNR最初のファイルにのみ適用されます。したがって、最初のファイルの場合:
    • a[$1]=$2$1indexとvalueで$2配列に入れますa
    • nextこのスクリプト行の残りの部分をスキップします。

言い換えればnext残りのスクリプトは、2番目のファイルに対してのみ実行されます。(そして3番目、4番目...ファイルが存在する場合)。

  • $3 in a && $3 = a[$3]3番目のフィールドが配列のキーである場合は、a3番目のフィールドをに置き換えますa[$3]。これは動作環境(つまり内部ではありません)にはないため、両方の{}条件がtrueの場合は現在のレコードを印刷する必要があります。そうでなければ何もできません。

一般的に言えば、右側の条件は割り当てなので、左側が真の場合、結果は真です。ただし、空の文字列または数値ゼロが割り当てられている場合、割り当てはfalseと評価されます。これは意図的かもしれませんが、しばしばプログラマーが気付かない極端なケースです。それを見るには、awkコードを試してください

filez:

111,111
112,114
113,113
000,000

filex:

A,bb,111,xxx,nnn
A,cc,112,yyy,nnn
A,dd,113,zzz,ppp
A,ee,000,uuu,aaa

最後の行の場合、$3 in a割り当て$3 = a[$3] はゼロなので、その行は印刷されません。

$ awk 'BEGIN{OFS=FS=","}NR==FNR{a[$1]=$2;next}$3 in a && $3 = a[$3]' filez filex
A,bb,111,xxx,nnn
A,cc,114,yyy,nnn
A,dd,113,zzz,ppp

OPが要求した説明:

覚えておいてください:配列は次のもので埋められます。a[$1]=$2 最初のファイルからfilez.が
$3 = a[$3]実行されました。2番目のファイルの場合filex
例:2行目ではfilez- a[$1]=$2> a[112] = 114。 2行目はfilex- $3 = a[$3]>です112=a[112]=114

関連情報