bash 函数 : enclosing the body in braces vs. 括号

标签 bash function parentheses curly-braces

通常,bash 函数是使用花括号将函数体括起来定义的:

foo()
{
    ...
}

今天在处理大量使用函数的 shell 脚本时,我遇到了被调用函数中与调用函数中具有相同名称的变量的问题,即这些变量是相同的。然后我发现可以通过将函数内的局部变量定义为局部变量来避免这种情况:local var=xyz

然后,在某个时候,我发现了一个线程(Defining bash function body using parenthesis instead of braces),其中解释说使用这样的括号定义函数同样有效:

foo()
(
    ...
)

这样做的效果是函数体是在子shell中执行的,好处是函数有自己的变量作用域,这样我就可以不用local来定义它们。由于拥有一个函数局部作用域似乎比所有变量都是全局的更有意义并且更安全,我立即问自己:

  • 为什么默认使用大括号而不是圆括号括起函数体?

但是,我很快也发现了在子 shell 中执行函数的一个主要缺点,特别是从函数内部退出脚本不再起作用,而是迫使我处理整个调用树的返回状态 (在嵌套函数的情况下)。这让我想到了这个后续问题:

  • 使用圆括号代替大括号是否还有其他主要缺点 (*)(这或许可以解释为什么大括号似乎更受青睐)?

(*) 我知道(从我随时间偶然发现的与异常相关的讨论中)有人会争辩说,明确使用错误状态比能够从任何地方退出要好得多,但我更喜欢后者。

显然,这两种风格各有优缺点。所以我希望你们中一些更有经验的 bash 用户能给我一些一般性的指导:

  • 什么时候应该使用大括号括起函数体,什么时候改用圆括号比较合适?

编辑:从答案中摘录

感谢您的回答,我现在对这个问题有了更清晰的认识。所以我从答案中得到的是:

  • 坚持使用传统的大括号,即使只是为了不混淆脚本的其他潜在用户/开发人员(如果整个主体都包含在括号中,甚至使用大括号)。

    <
  • 花括号唯一真正的缺点是可以更改父作用域中的任何变量,尽管在某些情况下这可能是一个优点。这可以通过将变量声明为 local 来轻松规避。

  • 另一方面,使用括号可能会产生一些严重的不良影响,例如弄乱退出、导致终止脚本和隔离变量范围的问题。

最佳答案

Why are braces used by default to enclose the function body instead of parentheses?

函数体可以是任何复合命令。这通常是 { list; },但技术上允许使用其他三种形式的复合命令:(list)((expression))[[ expression ]]

C 和 C 家族中的语言,如 C++、Java、C# 和 JavaScript 都使用大括号来分隔函数体。对于熟悉这些语言的程序员来说,大括号是最自然的语法。

Are there other major downsides (*) to using parentheses instead of braces (which might explain why braces seem to be preferred)?

是的。有许多事情您不能从子 shell 执行,包括:

  • 改变全局变量。变量更改不会传播到父 shell。
  • 退出脚本。 exit 语句将仅退出子 shell。

启动子 shell 也会严重影响性能。每次调用该函数时,您都会启动一个新进程。

如果您的脚本被终止,您也可能会遇到奇怪的行为。父 shell 和子 shell 收到的信号将发生变化。这是一个微妙的效果,但如果您有 trap 处理程序或您 kill 您的脚本,这些部分将无法按您希望的方式工作。

When shall I use curly braces to enclose the function body, and when is it advisable to switch to parentheses?

我建议您始终使用大括号。如果你想要一个显式的子 shell,那么在花括号内添加一组括号。仅使用括号是一种非常不寻常的语法,会使许多阅读您的脚本的人感到困惑。

foo() {
   (
       subshell commands;
   )
}

关于bash 函数 : enclosing the body in braces vs. 括号,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27801932/

相关文章:

javascript - 向单个按钮添加第二个功能

c - 运行生成器字时发生段违规

linux - java.lang.NoSuchMethodError : No such DSL method 'bash' found among steps 错误

string - 将具有相似名称的文件连接在一起

linux - 使用 ${1 :1} in bash

java - 明显的括号不好吗?

python - 获取嵌套括号中的所有文本 (Python)

linux - 在变量中写入命令的 PID

c++ - C++- “Multiple Definition of functions”如何解决?

C 中的括号会导致隐式转换吗?