函数定义为:
do_something () {
do it
}
我可以理解它的名称“do_something”和用于封装操作代码的花括号,但无法理解()
这里的用途,因为 Bash 脚本中没有命名参数。将其定义为可能更好、更直接
do_something {
do it
}
这与它当前的语法并不冲突,甚至还声明没有命名参数。here 的用法是什么()
?
答案1
如果没有()
,语法确实会变得模棱两可。
必须有一些定义函数的明确语法,并且不进行实质性的改变其他shell 语法,它不能是这样的:
do_something {
# one or more commands go here
}
你说这“与当前语法不冲突”,但事实确实如此!请注意,当你尝试运行第一行。您会收到错误,但这不是语法错误。第二行带有}
,是语法错误,但第一行不是。相反,do_something {
尝试运行名为 的命令do_something
并将它{
作为参数传递给该命令:
$ do_something {
do_something: command not found
如果已经有一个名为 的命令do_something
,则您正在运行它。如果已经有一个名为 的函数do_something
,你正在调用它。语法清晰是很重要的,但具体来说,能够重新定义函数而不意外调用它也是很重要的。定义函数和调用函数不应该看起来一样。
shell 如何处理{
和(
。
正如type {
将要告诉您的,{
是一个 shell 关键字。这使得它类似于[[
。如果在它本来是命令的情况下使用,则{
带有特殊语义。具体来说,它执行命令分组。但是,在其他情况下,它可能不经转义就用来表示文字{
字符。这包括将其作为命令的第二个或后续单词传递的情况。
当然,Bash可以被设计为{
以不同于当前的方式处理。但是,其语法将不再与 POSIX shell 兼容,并且 Bash 不会真正成为 Bourne 风格的 shell,也无法运行许多 shell 脚本。
相反,(
是 shell 元字符。如果它出现在命令中且未加引号(使用'
'
、"
"
或\
),则始终会受到特殊处理。因此语法中没有歧义:
do_something() {
# one or more commands go here
}
这不可能意味着其他任何事情。如果 Bash 没有函数,那么这将是一个语法错误,因为echo foo(bar)
语法错误的原因相同。
如果你真的不喜欢这种()
表示法,那么你可以使用关键字function
并省略它,就像sududus 提到。请注意,这是不是在大多数其他 Bourne 风格的 shell 中,这是定义函数的语法的一部分——在某些 shell 中,它是受支持的,但以这种方式定义的函数有不同的语义——因此使用它的脚本将不可移植。(这种语法之所以能够明确无误,是因为它function
本身就是 Bash 中的一个关键字,表示跟在它后面的内容是函数定义的开始。)
最后,请注意,虽然大多数函数定义{
在实践中使用,但允许使用任何复合命令。如果您有一个函数体,您希望它始终在子 shell 中运行,则可以使用(
)
而不是{
}
。
答案2
标记()
用于告诉 shell 解释器你正在声明一个函数。
$ do_something () { echo 'do it'; } ; do_something
do it
另一种选择bash
是function
function do_something {
echo 'do it'
}
或者你可以测试一下
$ bash -c "function do_something { echo 'do it'; } ; do_something"
do it
答案3
非常一个真正的大括号样式-你们当中的一个人!
考虑其他非常好的支撑样式:
foo
{
...
}
foo
{
...
}
foo
while ...; do ...; done # Look, ma! No braces!
foo
( ... ) # Look, ma! No braces and a subshell to boot!
shell 如何判断这些是函数定义而不是简单的命令foo
后跟命令列表?在所有这些情况下,都需要一个额外的消歧因素,如()
或关键字。function