Bash 如何标记脚本?

How Does Bash Tokenize Scripts?

来自 C++:对我来说,某些白色 space 对脚本的有效性或语义有影响总是很神奇。这是一个例子:

echo a 2 > &1

bash: syntax error near unexpected token `&'

echo a 2 >&1

a 2

echo a 2>&1

a

echo a 2>& 1

a

查看 this 并没有多大帮助。我的主要问题是感觉不一致;我很困惑。

我正在尝试了解 bash 如何标记其脚本。对其进行一般性描述以消除任何混淆将不胜感激。

编辑: 我不是专门寻找重定向。他们只是举个例子。其他示例:

A="something"
A = "something"
if [$x = $y];
if [ $x = $y ]; 

为什么 ] 和 ; 之间不需要 space?为什么赋值需要立即等号? ...

2>&1 是一个单独的运算符标记,因此任何将其分开的空格都会改变命令的含义。它恰好是一个 参数化 令牌,这意味着 shell 将进一步对其进行令牌化以确定运算符的确切作用。一般形式是 n>&m,其中 n 是您要重定向的文件描述符,而 m 是您要复制到的描述符。在这种情况下,您是说命令的标准错误 (2) 应该复制到当前打开的任何标准输出 (1)。

你举的例子有很好的理由。

  • 重定向源默认为 FD 1。因此,>&1 本身是合法的语法——它将 FD 1 重定向到 FD 1——这意味着在 > 之前允许空格会导致不明确的语法:解析器无法判断前面的标记是它自己的词还是重定向源。
  • >& 下,除 FD 编号外,其他任何内容均无效,除非您使用的是非常新的 bash,它允许取消引用变量以检索 FD 编号。在任何情况下,紧跟在 >& 之后的任何内容都被认为是文件描述符,因此允许可选的空格不会产生歧义。
  • a = 1 被解析为合法命令,而不是语法错误:它运行带有第一个参数 = 和第二个参数 1 的命令 a。不允许在赋值中使用空格消除了这种歧义。类似地,a= foo 具有独立且不同的含义:它导出一个空值的环境变量 a,而 运行 命令 foo。放宽空格规则将不允许这两个合法命令。
  • [ 是一个命令,不是解析器已知的特殊语法;因此,[foo 试图找到一个命令(命名为 /usr/bin/[foo),需要空格。
  • ; 在解析器中优先作为语句分隔符,而不是被视为单词的一部分,除非引用或转义。 &(另一个分隔符)或换行符也是如此。

事实是,没有一个通用规则可以解释这一切;你需要 read and learn the language syntax。幸运的是,没有 非常多 语法:几乎所有命令都是 "simple commands",它们遵循非常简单明了的规则。你问的是,我们正在解释,一些例外情况;还有其他例外,例如bash中的[[ ]],但它们的总数足够小,可以学习。


其他建议资源: