我可能在这里遗漏了一些非常简单的东西,但是当我说
echo 'The quick brown fox jumped over the lazy dog.' | \
awk '{
split($0, WORDS, " ");
for ( WORD in WORDS ) {
print $WORD;
}
}'
Run Code Online (Sandbox Code Playgroud)
我得到这个回报:
quick
brown
fox
jumped
over
the
lazy
dog.
The
Run Code Online (Sandbox Code Playgroud)
为什么第一个字最后打印?
$ awk --version
awk version 20070501
Run Code Online (Sandbox Code Playgroud)
首先,for (i in array)
在awk
yield 数组的索引,而不是数组元素。所以你得到了你访问的结果$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
Run Code Online (Sandbox Code Playgroud)
您可以看到在访问变量时获得了数组索引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
Run Code Online (Sandbox Code Playgroud)
(使用 GNU sed
,您需要sed -u 1q
)
您不是在打印数组的元素,而是按顺序打印字段。在 中awk
,变量不以 a 为前缀$
,即字段。因此,$a
将打印存储在a
. 要打印一个变量,比如说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
Run Code Online (Sandbox Code Playgroud)
你追求的是:
$ 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.
Run Code Online (Sandbox Code Playgroud)
其中,在 GNU 中awk
,相当于:
$ echo 'The quick brown fox jumped over the lazy dog.' | awk '{
for (i=1; i<=NF;i++){
print $i
}
}'
Run Code Online (Sandbox Code Playgroud)
虽然gawk
(GNU awk
)split
将按照找到的顺序对数组进行排序(如上所示),但其他实现不会这样做,正如 cuonglm 在他的回答中所解释的那样。因此,split
您可以设置字段分隔符和 letawk
来进行拆分,而不是使用。在您的示例中,由于分隔符是一个空格,因此没有必要,但以下是其他情况下的操作方法:
$ 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.
Run Code Online (Sandbox Code Playgroud)