我注意到 KSH 和 Bash 之间的差异,我正在寻找记录在何处的差异,或者寻找其中一个或另一个是错误的确认。
在 Korn Shell 中(见于 KSH88 和 KSH93),此命令工作正常,并打印结果“yes”:
if [[ -z "" ]] then echo yes ; fi # Note no ';' after the ']]'
在 Bash 中,我在意外标记“then”附近遇到语法错误
。
仅当我使用双括号时才会出现此行为。如果我使用单括号形式的条件表达式,KSH 和 Bash 都会给我一个没有分号的语法错误,但会提示 fi
而不是 then
。
这是错误还是功能?在 ksh 或 Bash 中?我注意到 Bash 和 ksh 的手册页对 if
的语法略有不同,但这种差异似乎不适用于这种情况。
编辑:有人 (@jp48) 指出了 bash
和 ksh
man 之间语法定义的显着差异页。但是,查看 Solaris (11.3) man page , 匹配 AST source code ,语法为:
if list ;then list [ ;elif list ;then list ] ... [ ;else list ] ;fi
它与 Bash 手册页之间的区别在于分号在 elif
/else
/fi
之前的位置(不是存在) > 而不是在 list
之后:
if list; then list; [ elif list; then list; ] ... [ else list; ] fi
没有分号的替代语法来自 ksh 的公共(public)域版本(可能是 PDksh),而不是“官方”ksh 版本。
最佳答案
TL;DR:根据 ksh man page,这不是错误.
[
和 [[
的主要区别在于 [
是关键字,而 [[
是两个 shell 中的内置函数。请注意,出于性能原因,“回退可执行文件”/bin/[
(本质上是 /bin/test
)从未使用过,但如果我们假装以下内容会更好理解此命令已执行。
然后值得注意的是 ]]
也是一个关键字,但是 ]
只是传递给 [
/test< 的参数
.
这里有一些证据(两个 shell 的输出几乎相同):
$ type [[
[[ is a shell keyword
$ type ]]
]] is a shell keyword
$ type [
[ is a shell builtin
$ type ]
***: not found
解释完之后,让我们看看您的示例中会发生什么。
bash 的行为符合预期 man page (即它需要 ;
):
if list; then list; [ elif list; then list; ] ... [ else list; ] fi
然后让我们关注 ksh,作为引用,我将使用 FreeBSD 的 man page .
ksh中if
的语法如下
if list then list [elif list then list] ... [else list] fi
以及 ksh 中的列表:
must end with a semicolon, a newline or a (syntactically correct) reserved word
所以 [...]
没有 ;
不是有效的列表(记住最后一个 ]
既不是关键字也不是内置函数,而是传递给 [
] 的“参数”。
而 [[...]]
是一个有效的列表,因为 ]]
是一个语法上正确的保留字.
总之,这不是一个错误,因为它符合规范;当然,最好不要使用 ;
(或换行符)并且可能不符合 POSIX。
关于bash - 为什么 "if [[ ... ]] then"(没有分号或换行符)在 ksh 中有效但在 bash 中无效?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48107383/