shell 函数定义中括号 `()` 有什么用?

shell 函数定义中括号 `()` 有什么用?

函数定义为:

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

另一种选择bashfunction

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

相关内容