
おそらくここで非常に簡単なものを見逃しているかもしれませんが、
echo 'The quick brown fox jumped over the lazy dog.' | \
awk '{
split($0, WORDS, " ");
for ( WORD in WORDS ) {
print $WORD;
}
}'
私はその代償としてこれを得ます:
quick
brown
fox
jumped
over
the
lazy
dog.
The
最初の単語が最後に印刷されるのはなぜですか?
$ awk --version
awk version 20070501
答え1
まず、Yieldfor (i in array)
にあるのはawk
配列要素ではなく配列のインデックスです。だからあなたは訪問したのと同じ結果を得ます$1
。 ....$2
$NF
echo 'The quick brown fox jumped over the lazy dog.' | \
awk '{
split($0, WORDS, " ");
for ( WORD in WORDS ) {
print WORD;
}
}'
2
3
4
5
6
7
8
9
1
変数にアクセスすると、配列インデックスを取得するのがわかりますWORD
。
あなたの質問に対して、POSIXはawk
配列ループを介して配列インデックスの生成を定義します。指定された注文はありません。:
for(配列の変数)
繰り返して、配列の各インデックスを変数に割り当てます。 指定された注文はありません。。
したがって、定義は実装に依存します。どのように配列を繰り返します。
私のシステムのクイックテストは、次のように増加する順序gawk
で繰り返されることを示していますmawk
。
for AWK in gawk mawk /usr/5bin/[on]awk /usr/5bin/posix/awk; do
printf '==%s==\n' "$AWK"
echo 'The quick brown fox jumped over the lazy dog.' |
"$AWK" '{
split($0, WORDS, " ")
for (WORD in WORDS) {
print WORD;
}
}' | { sed 1q; tail -n1 }
done
==awk==
1
9
==mawk==
1
9
==/usr/5bin/nawk==
2
1
==/usr/5bin/oawk==
2
1
==/usr/5bin/posix/awk==
2
1
(GNUを使用するsed
とsed -u 1q
)
答え2
配列の要素を印刷する代わりに、フィールドを順次印刷します。では変数の前に、つまりフィールドがawk
付いていません。$
したがって、$a
フィールドに保存されているすべての数字が印刷されますa
。たとえば、変数を印刷するにはnoがfoo
必要です。print foo
$
配列を繰り返すと、awk
配列のインデックスが繰り返されます。
$ echo 'The quick brown fox jumped over the lazy dog.' | awk '{
split($0, WORDS, " ");
for ( WORD in WORDS ) {
print WORD;
}
}'
1
2
3
4
5
6
7
8
9
あなたが求めるものは次のとおりです
$ echo 'The quick brown fox jumped over the lazy dog.' | awk '{
split($0, WORDS, " ");
for ( WORD in WORDS ) {
print WORDS[WORD];
}
}'
The
quick
brown
fox
jumped
over
the
lazy
dog.
GNUでは、awk
次のようになります。
$ echo 'The quick brown fox jumped over the lazy dog.' | awk '{
for (i=1; i<=NF;i++){
print $i
}
}'
gawk
(GNU awk
)はsplit
見つけた順序で配列をソートしますが(上記のように)、cuonglmが彼の答えで説明したように、他の実装ではこれを行いません。したがって、split
フィールド区切り文字を設定し、awk
代わりにletを使用して分割を実行できます。あなたの例では、区切り文字は空白なので必要ありませんが、他の場合は区切り文字を使用する方法は次のとおりです。
$ echo 'The-quick-brown-fox-jumped-over-the-lazy-dog.' |
awk -F"-" '{
for(i=1;i<=NF;i++){
print $i
}
}'
The
quick
brown
fox
jumped
over
the
lazy
dog.
答え3
$1
$2
あなたの例では、各フィールドなどを印刷できるという事実を無視して配列内の要素の数をsplit
返すので、表示される順序で繰り返すには、次のように使用できます。
echo 'The quick brown fox jumped over the lazy dog.' | \
awk '{
n = split($0, WORDS, " ");
for (i = 1; i <= n; ++i) {
print WORDS[i];
}
}'
他の人が述べたように、配列がナビゲートされる順序は使用時に指定されませfor (indx in array)
ん(GNU awkを使用すると制御できますが)。