shell函数定义中括号`()`的用法是什么?
函数定义为:
do_something () { do it }
我可以理解它的名字’do_something’和大括号来封装动作代码,但我无法理解这里的()
目的是什么,因为Bash脚本中没有命名参数。 将其定义为可能更好,更直接
do_something { do it }
这与其当前语法不冲突,甚至更多声明没有命名参数。 ()
的用法是什么?
没有()
,语法真的很模糊。
必须有一些明确的语法来定义一个函数,并且在没有实质上改变其他 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
并省略它,就像sudodus提到的那样 。 请注意,这不是在大多数其他Bourne样式shell中定义函数的语法的一部分 – 在某些情况下,它受支持但是以这种方式定义的函数具有不同的语义 – 因此使用它的脚本将不可移植。 (这种语法能够明确的原因是function
本身就是Bash中的一个关键字,表示其后面的任何内容都是函数定义的开头。)
最后,请注意,虽然大多数函数定义使用{
实际上,但允许使用任何复合命令。 如果你有一个你希望总是在子shell中运行的函数,你可以使用(
)
而不是{
}
。
()
令牌是告诉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
你是多么的真正支撑式的主义者!
考虑其他完美的支撑样式:
foo { ... } foo { ... } foo while ...; do ...; done # Look, ma! No braces! foo ( ... ) # Look, ma! No braces and a subshell to boot!
shell如何告诉那些是函数定义而不仅仅是命令foo
后跟命令列表? 在所有这些情况下,需要一个额外的歧义因素,如()
或function
关键字。