【问题标题】:Bash command groups: Why do curly braces require a semicolon?Bash 命令组:为什么大括号需要分号?
【发布时间】:2014-02-10 08:43:43
【问题描述】:

grouping commands in bash 时,我知道括号() 和花括号{} 之间在用途上的区别。

但是为什么大括号结构在最后一个命令之后需要分号,而对于括号结构,分号是可选的?

$ 而假;做(回声“你好”;回声“再见”;);完毕 $ 而假;做(回声“你好”;回声“再见”);完毕 $ 而假;做{回声“你好”;回声“再见”; };完毕 $ 而假;做{回声“你好”;回声“再见”};完毕 bash:意外标记“完成”附近的语法错误 $

我正在寻找一些关于为什么会这样的见解。我不是在寻找诸如“因为文档是这样说的”或“因为它是这样设计的”之类的答案。我想知道为什么它是这样设计的。或者如果它只是一个历史文物?

至少可以在以下版本的 中观察到这一点:

  • GNU bash,版本 3.00.15(1)-release (x86_64-redhat-linux-gnu)
  • GNU bash,版本 3.2.48(1)-release (x86_64-apple-darwin12)
  • GNU bash,版本 4.2.25(1)-release (x86_64-pc-linux-gnu)

【问题讨论】:

  • 为了参考起见,注意测试时使用的 bash 版本可能会有所帮助。
  • @JonathonReinhart - 版本已在问题中注明 - 谢谢。
  • “因为那是how it's documented”怎么样。大括号和小括号之间的细微区别描述得很清楚。
  • 虽然这有一个很好的答案并且此时不值得结束,但请参阅What is the rationale for closing "why" questions on language design? -- 请注意,SO 的范围仅限于实用、可回答的问题。如果一个问题本质上是历史问题,它不会改变您参与开发实践的方式。

标签: bash bash syntax grouping parentheses braces


【解决方案1】:

因为{} 仅在它们是命令中的第一个单词时才被识别为特殊语法。


这里有两个重点,都可以在bash手册的definitions section找到。首先是元字符的列表:

metacharacter

不加引号时用于分隔单词的字符。元字符是空格或以下字符之一:“|”、“&”、“;”、“(”、“)”、“”。

该列表包括括号,但不包括大括号(既不是花括号也不是方括号)。请注意,它不是对 shell 具有特殊含义的字符的完整列表,而是分隔标记的字符的完整列表。因此{} 不分隔标记,并且仅当它们与元字符(例如空格或分号)相邻时才会被视为标记本身。

虽然大括号不是元字符,但它们在parameter expansion(例如${foo})和brace expansion(例如foo.{c,h})中被shell特殊处理。除此之外,他们只是普通的角色。例如,命名文件{ab}}{ 没有问题,因为这些词不符合参数扩展(要求${ 之前)或大括号扩展( {} 之间至少需要一个逗号)。就此而言,您可以使用 {} 作为文件名,而无需引用符号。同样,您可以调用文件ifdonetime,而无需考虑引用名称。

后面的这些标记是“保留字”:

reserved word

一个对 shell 有特殊含义的词。大多数保留字都会引入 shell 流控制结构,例如 forwhile

bash 手册不包含保留字的完整列表,这很遗憾,但它们肯定包含 Posix 指定的:

!    {    }
case do   done elif else
esac fi   for  if   in
then until while

以及由 bash(和其他一些 shell)实现的扩展:

[[   ]]
function  select time

这些词与内置词(如[)不同,因为它们实际上是shell 语法的一部分。内置函数可以实现为函数或 shell 脚本,但保留字不能,因为它们改变了 shell 解析命令行的方式。

保留字有一个非常重要的特性,它实际上并没有在 bash 手册中突出显示,但在 Posix 中非常明确(上面的保留字列表取自其中,time 除外):

这种识别[作为保留字]只有在没有任何字符被引用并且该词被用作以下情况时才会发生:

  • 命令的第一个字……

(识别保留字的位置的完整列表略长,但上面是一个很好的总结。)换句话说,保留字仅在它们是命令的第一个字时被保留。而且,由于{} 是保留字,它们只有在命令中的第一个字是特殊语法时才属于特殊语法。

例子:

ls }  # } is not a reserved word. It is an argument to `ls`
ls;}  # } is a reserved word; `ls` has no arguments

关于 shell 解析,尤其是 bash 解析,我还可以写很多,但很快就会变得乏味。 (比如#什么时候开始评论,什么时候只是一个普通字符的规则。)大概的总结是:“不要在家里尝试这个”;实际上,唯一可以解析 shell 命令的就是 shell。并且不要试图理解它:它只是任意选择和历史异常的随机集合,其中许多但并非全部基于不破坏具有新功能的古老 shell 脚本的需要。

【讨论】:

  • 正如 OP 所发现的那样,它们显然很特别,也许您可​​以详细说明它们为何特别,以及 “如果它们是命令中的第一个单词”有什么意义我>?
  • @Kev,一如既往,因为设计师如此决定。实际上,它允许您编写echo {} 并打印{}
  • @rici +1 表示精确和简洁。
  • 值得注意的是{}被定义为保留字,而不是像()这样的控制操作符。
  • @DigitalTrauma:你去吧。回到同一个地方的大量单词,包括一个非常象征性的示例和许多指向更多信息的链接。阅读完所有内容后,请告诉我它是否对原始简洁答案有任何改进。
猜你喜欢
  • 2013-08-21
  • 1970-01-01
  • 2014-08-09
  • 1970-01-01
  • 2019-10-27
  • 1970-01-01
  • 2013-05-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多