bash - 为什么 "if [[ ... ]] then"(没有分号或换行符)在 ksh 中有效但在 bash 中无效?

标签 bash shell ksh

我注意到 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) 指出了 bashksh 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/

相关文章:

python - iMac上的Shell脚本不再与High Sierra一起使用

node.js - 安装 yeoman 时出错

linux - 将 "module"别名(调用 modulecmd)从 tcsh 适配到 bash

shell - 关于 KornShell 中的 'for' 循环

bash - 在Linux脚本中,是否可以在同一个进程中执行多个命令?

mysql - 在 Bash 中声明变量?

xcode - 如何使用 bash 查找文本字符串 --> "PROVISIONING_PROFILE[sdk=iphoneos*]"<--这个字符串有很多特殊字符

linux - 匹配目录中的目录

java - Autosys 文件观察器