AcB*_*Bap 9 command-line syntax ksh
例如,以下命令不起作用:
if [[-e xyz]]; then echo File exists;fi
Run Code Online (Sandbox Code Playgroud)
ksh 给出以下错误
[[-e: command not found
Run Code Online (Sandbox Code Playgroud)
那是因为“[[-”不明确吗?
Ser*_*nyy 15
最简单的解释是,因为在手册中它显示为[[ expression ]]
所以必须在[[
andexpression
和 closed之间有空间]]
。但是我们当然可以尝试更深入地研究它。Shell 的语法有些复杂,并且在很大程度上依赖于“分词”的概念。特别是, ksh(1)手册指出:
shell 通过将其分解为单词来开始解析它的输入。作为字符序列的单词由不带引号的空白字符(空格、制表符和换行符)或元字符(<、>、|、;、&、(和))分隔。除了分隔单词之外,空格和制表符也被忽略,而换行符通常用于分隔命令。
因此,如手册中所述,字符序列[[-e
被视为外壳词。ksh
将在内置命令和特殊运算符(如for
或while
)列表中查找此类命令,然后查找外部命令 - 瞧 - 没有找到,因此会出现有关未找到命令的错误消息。
在这种情况下[[
也不是特殊的元字符。如果是,则-e
in 部分[[-e
将被视为一个 shell 词,而不是其[[
自身的参数。但是,[[
被描述为复合命令,并且手册说如下:
复合命令是使用以下保留字创建的——这些字只有在它们没有被引号引起来并且用作命令的第一个字时才能被识别(即,它们前面不能有参数分配或重定向):
因此,为了[[
被识别为复合命令,它必须是命令或命令列表的第一个单词,根据之前对“单词”的定义,这意味着它必须用空格、制表符或换行符与其他单词隔开词/论点。
你在评论中问过:“为什么解析器不能在找到“[[”模式后立即停止,并将其视为条件命令的开始?简短的回答可能是因为 1)[
语法的影响,因为它最初是一个外部命令,对于 POSIX 标准合规性,即使在今天也作为外部命令存在,2) 因为 shell 解析器是这样构建的。Shell 解析器可以识别其他非空格分隔的特殊字符: echo $((2+2))
并且(echo foobar)
工作得很好。也许将来当ksh
开发恢复或出现分叉或克隆(如mksh
或pdksh
)时,有人会在[[-e
.
[[
被称为“保留字”(参见Shell Command Language 的 2.9 节)。根据 POSIX 定义,保留字必须用空格分隔。相比之下,(
是一个运算符,并且标准在第 2.9 节中指出“在某些不需要<blank>
s 的地方(当其中一个令牌是运算符时),表示包括令牌之间的间距”。请参阅相关讨论: POSIX Shell 语法:为什么 Brace Group 需要第一个空格而 Subshell 不需要?