私は初めて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==FNR
falseの場合、NR==FNR
trueの場合は$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
段階的に起こるものは次のとおりです。
filez
最初の行はtrueNR==FNR
と評価されます1==1
。したがって、{a[$1]=$2;next}
実行はスクリプトの残りの部分をスキップすることを意味しますa[111]
(特に現在は使用されていません)。111
next
$3 in a && $3 = a[$3]
$3
filez
2番目と最後の行はNR==FNR
と評価され、2==2
再び何も印刷されないために設定されます。{a[$1]=$2;next}
a[112]
114
$3 in a && $3 = a[$3]
next
filex
最初の行を読むと、falseNR==FNR
と評価されます。3==1
{a[$1]=$2;next}
いいえ次の条件付き:$3
はの111
インデックス値a
なのでtrue$3 in a
で評価されます$3 = a[$3]
。結果は空の文字列ではないため、条件付き割り当てもtrueと評価され、現在の行が印刷されます。a[111]
111
$3
111
0
A,bb,111,xxx,nnn
filex
2番目と最後の行を読み取ると、falseNR==FNR
と評価されます。4==2
{a[$1]=$2;next}
いいえ次の条件付き: と は のインデックス値なので true なので評価されます。結果は空の文字列ではない$3
ため、条件付き割り当てもtrueと評価され、現在の行が印刷されます。112
a
$3 in a
$3 = a[$3]
a[112]
114
$3
114
0
A,cc,114,yyy,nnn
答え2
BEGIN{OFS=FS=","}
入力フィールドと出力フィールドの区切り記号をに設定します,
。NR==FNR
最初のファイルにのみ適用されます。したがって、最初のファイルの場合:a[$1]=$2
$1
indexとvalueで$2
配列に入れますa
。next
このスクリプト行の残りの部分をスキップします。
言い換えればnext
。残りのスクリプトは、2番目のファイルに対してのみ実行されます。(そして3番目、4番目...ファイルが存在する場合)。
$3 in a && $3 = a[$3]
3番目のフィールドが配列のキーである場合は、a
3番目のフィールドをに置き換えます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
。