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中的[[ ]]
,但它们的总数足够小,可以学习。
其他建议资源:
- http://aosabook.org/en/bash.html(开源应用程序的架构;关于 bash 的章节)
- http://mywiki.wooledge.org/BashParser(Wooledge wiki 对解析器的高级描述——尽管这更侧重于扩展规则而不是标记化)
- http://mywiki.wooledge.org/BashGuide(一般 bash 语法的介绍性指南,与一些竞争材料相比,更注重准确性和最佳实践)。
来自 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中的[[ ]]
,但它们的总数足够小,可以学习。
其他建议资源:
- http://aosabook.org/en/bash.html(开源应用程序的架构;关于 bash 的章节)
- http://mywiki.wooledge.org/BashParser(Wooledge wiki 对解析器的高级描述——尽管这更侧重于扩展规则而不是标记化)
- http://mywiki.wooledge.org/BashGuide(一般 bash 语法的介绍性指南,与一些竞争材料相比,更注重准确性和最佳实践)。