Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash命令组:为什么花括号需要分号?_Bash_Syntax_Grouping_Parentheses_Braces - Fatal编程技术网

Bash命令组:为什么花括号需要分号?

Bash命令组:为什么花括号需要分号?,bash,syntax,grouping,parentheses,braces,Bash,Syntax,Grouping,Parentheses,Braces,我知道括号()和大括号{}在使用时的不同 但是为什么花括号构造在最后一个命令后需要分号,而对于圆括号构造,分号是可选的 $ while false; do ( echo "Hello"; echo "Goodbye"; ); done $ while false; do ( echo "Hello"; echo "Goodbye" ); done $ while false; do { echo "Hello"; echo "Goodbye"; }; done $ while false; do

我知道括号
()
和大括号
{}
在使用时的不同

但是为什么花括号构造在最后一个命令后需要分号,而对于圆括号构造,分号是可选的

$ while false; do ( echo "Hello"; echo "Goodbye"; ); done $ while false; do ( echo "Hello"; echo "Goodbye" ); done $ while false; do { echo "Hello"; echo "Goodbye"; }; done $ while false; do { echo "Hello"; echo "Goodbye" }; done bash: syntax error near unexpected token `done' $ $whilefalse;做(回音“你好”回音“再见”);完成 $whilefalse;做(回声“你好”;回声“再见”);完成 $whilefalse;做{echo“你好”;echo“再见”};完成 $whilefalse;做{echo“你好”;echo“再见”};完成 bash:意外标记“完成”附近出现语法错误 $ 我想了解一下为什么会这样。我不是在寻找这样的答案,比如“因为文档上这么说”或者“因为它是这样设计的”。我想知道为什么它是这样设计的。或者如果它只是一件历史文物

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

  • GNUBash,版本3.00.15(1)-发行版(x86_64-redhat-linux-GNU)
  • GNUBash,版本3.2.48(1)-发布版(x86_64-apple-darwin12)
  • GNUBash,版本4.2.25(1)-发行版(x86_64-pc-linux-GNU)

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


      这里有两个要点,它们都可以在bash手册的中找到。首先是元字符列表:

      元字符

      一种字符,在不加引号的情况下分隔单词。元字符是空白字符或以下字符之一:“|”、“&”、“;”、”(“,”)“,”

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

      尽管大括号不是元字符,但它们在(例如
      ${foo}
      )和(例如
      foo.{c,h}
      )中被shell特别处理。除此之外,他们只是普通的角色。例如,命名文件
      {ab}
      ,或
      }{
      ,没有问题,因为这些单词不符合参数扩展(在
      {
      之前需要
      $
      )或大括号扩展(在
      {
      }
      之间至少需要一个逗号)的语法。就此而言,您可以使用
      {
      }
      作为文件名,而无需引用符号。类似地,您可以在不考虑引用名称的情况下调用文件
      (如果
      )、
      完成
      时间

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

      保留字

      对shell有特殊意义的词。大多数保留词引入shell流控制结构,如
      for
      while

      bash手册没有包含完整的保留字列表,这是不幸的,但它们肯定包括指定的Posix:

      !    {    }
      case do   done elif else
      esac fi   for  if   in
      then until while
      
      以及bash(和其他一些shell)实现的扩展:

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

      保留字有一个非常重要的特性,实际上在bash手册中没有突出显示,但在中非常明确(从中获取了上述保留字列表,除了
      时间
      ):

      该识别[作为保留字]仅在未引用任何字符且该字用作:

      • 命令的第一个字
      (识别保留字的位置的完整列表稍长,但上面是一个很好的总结。)换句话说,保留字仅在它们是命令的第一个字时被保留
      是保留字,仅当它们是命令中的第一个字时才是特殊语法

      例如:

      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脚本的需要。

      为了参考,请注意在编写shell时使用的bash版本可能会有所帮助正在测试。@JonathonReinhart-问题中已经提到了版本-谢谢。那么“因为那是”大括号和圆括号之间的微妙区别已经清楚地描述了。虽然这是一个很好的答案,不值得就此结束,但请注意,SO的范围仅限于实际的、可回答的问题。如果一个问题本质上是历史性的,它不会改变你参与开发实践的方式。它们显然是特殊的l正如OP所发现的,也许你可以进一步说明它们为什么特别,以及“如果它们是命令中的第一个单词”的意义是什么?@Kev,一如既往,因为设计者决定这样做。事实上,它允许你编写
      echo{}
      并获得
      {}
      已打印。@rici+1用于精确和简洁。值得注意的是,
      {
      }
      被定义为保留字,而不是像
      @digitaltrampion:好了
      ls }  # } is not a reserved word. It is an argument to `ls`
      ls;}  # } is a reserved word; `ls` has no arguments