awkの印刷配列の結果を理解できませんか?

awkの印刷配列の結果を理解できませんか?

単純なfileインクルードの場合:

1        a
2        b
3        c
4        d
5        e
6        f
7        g
8        h
9        i
10       j

私は次のコマンドを使用します。

awk 'lines[NR]=$0 { print $lines[2]}' 

それは私に以下を与えます:

1        a
b
c
d
e
f
g
h
i
j

どうやってなぜ?こんなことはありませんか?

2 b

また、以下を更新すると

awk '{lines[NR]=$0} END { print lines[2]}' awk.write

2 b

そして使用$

j

答え1

awk変数とワークフローを混同しています。おそらく必要なものは次のとおりです(2行目のみ印刷)。

awk '{lines[NR]=$0} END{print lines[2]}' file

ただし、これは次のように簡単に行うことができます。

awk 'NR==2' file

質問に次のように指示します。

awk 'lines[NR]=$0 { print $lines[2]}' 
  • lines[NR]=$0awkここでは条件として解釈されます。awk次のメカニズムを持つワークフローがあります(すべての行に適用されます) 'condition{instructions}'lines[NR]=$0配列を埋めますが、これは常に真の条件です。これが、{...}コマンドブロックが各行に対して実行される理由です。
  • print $lines[2]配列の2番目の項目は印刷されませんlines[2]$lines[2]名前が配列の2番目の項目の内容である変数に展開されます。最初の行は初期化されていないため、print引数なしで呼び出されます。これは行全体を印刷することを意味します。ただし、(他のすべての行で)設定するとに展開されますprint $2。つまり、行の2番目のフィールドが印刷されます。

答え2

では、awk参照を通じて変数の値にアクセスできます。

$ awk 'BEGIN {var=1; print var}'
1

持つ特殊変数フィールド変数という$名前は、記号の後に数字または式が続くように表示されます。したがって、両方とも最初のフィールドの値を$1提供します。$(0+1)

linesあなたの例では、キーが行番号で値が完全な行である連想配列を作成しました。 forを2使用する必要があるキー値を取得するには、n番目のフィールドを参照する必要がありますlines[2]$lines[2]ここで、n番目はの戻り値ですlines[2]

最初の行を処理すると、初期化されずにlines[2]返されることがあります。0またはまたは他のもの(POSIXはこの動作を指定しません)。とにかく、printとはprint $0同じです。それで、その理由は最初の行1 aです。$0

2行目から始まり、lines[2]2行目の内容として割り当てられます。つまり2 b、数値コンテキストで2 b次を返します。2、2 番目の行から 2 番目のフィールドの値を取得する$2式です。


今後の式は、$POSIXで指定された数値結果を返すことは保証されていないため、次のようになります。

フィールド変数は、「$」の後に数字または数式が続く必要があります。この文脈では、非負の整数以外のものとして評価される未指定のフィールド数値式の効果は、初期化されていない変数または文字列値を数値に変換する必要はありません。

したがって、実装が中断される状況がある可能性があります。少なくともBrian Kernighan自身のバージョン:

$ echo 1 2 | bawk '{print $b}'
bawk: illegal field $(), name "b"
 input record number 1, file 
 source line number 1

0いずれにせよ、以下を追加することで、数値コンテキストで式を強制的に評価できます。

$ echo 1 2 | awk '{print $(b+0)}'
1 2

関連情報