我最近正在查看一些令我困惑的代码,因为它有效,但我没想到它会有效。代码简化为这个例子
#!/bin/bash
for var;
do
echo "$var"
done
当使用命令行参数运行时会打印它们
$ ./test a b c
a
b
c
正是这一点,(对我来说)是出乎意料的。为什么这不会导致错误,因为var
未定义?使用这个被认为是“好的做法”吗?
答案1
for
in value1 value2...
如果在所有类似 Bourne 的 shell 中未指定任何部分,则循环将在位置参数上循环。
从 70 年代末开始,Bourne shell 中就已经存在这种情况,但在 Bourne shell 中,您需要省略它;
(您也可以使用for i do
(除了在某些旧的 ash 版本中,您需要在 之前添加换行符do
))。
看Bash for 循环中“do”关键字的用途是什么?欲了解更多信息,包括更多奇怪变种。
正在做:
for i
do
something with "$i"
done
是很好的做法。它比通常的同类产品稍微更便携/更可靠:
for i in "$@"; do
something with "$i"
done
Bourne shell、ksh88 在某些情况下会出现一些问题(例如,当$#
Bourne shell 的某些版本中为 0 时(这${1+"$@"}
不是"$@"
可以解决的),或者当$IFS
Bourne 和 ksh88 中不包含空格字符时),或者当该nounset
选项已启用,并且$#
在某些 shell 的某些版本中为 0,包括bash
(再次${1+"$@"}
作为解决方法)。
答案2
这是默认行为,是的。它记录在help
关键字中for
:
terdon@tpad ~ $ help for
for: for NAME [in WORDS ... ] ; do COMMANDS; done
Execute commands for each member in a list.
The `for' loop executes a sequence of commands for each member in a
list of items. If `in WORDS ...;' is not present, then `in "$@"' is
assumed. For each element in WORDS, NAME is set to that element, and
the COMMANDS are executed.
Exit Status:
Returns the status of the last command executed.
因此,当您没有为其提供要迭代的列表时,它将默认迭代$@
位置参数数组(a
,在您的示例中)b
。c
而这种行为是由 POSIX 定义所以,是的,就目前而言,这被认为是“良好实践”。