以下代码适用于我尝试过的 Zsh 5.8,尽管缺少分号。但这真的是有效的 Zsh 语法吗?
#!/bin/zsh
if var='value' then
echo 'then'
fi
没有分配会导致parse error near `fi'
:
#!/bin/zsh
if true then
echo 'then'
fi
正确的语法,带分号:
#!/bin/zsh
if true; then
echo 'then'
fi
没有分号的代码在 sh、Bash 和 Ksh 93 中都是不正确的。
我很困惑 Zshif ... then
仅在某些情况下在同一行中接受不带分号的情况。条件位置的赋值似乎是一种特殊情况。该文档没有精确说明何时需要分号:
https://zsh.sourceforge.io/Doc/Release/Shell-Grammar.html#index-if-construct
实际上我担心的是 Ksh。当我尝试真正实现 Ksh 93 时,出现错误:syntax error at line ...: `fi' unexpected
。但是当我用 运行 Zsh 时emulate ksh
,效果很好。我想这之所以有效,只是因为它不是真正的 Ksh,而是 Zsh,而且在真正的 Ksh 中它始终是一个错误。有没有精确的文档可以证实这一点?
这是我在 sh、Ksh、Bash 和 Zsh 中的尝试,以及相应的输出: https://bitbucket.org/OPiMedia/hellanguages/src/master/comparative/shell/if_then/
答案1
分配后,允许发出命令。例如:
LC_ALL=C grep foo file
rc
在任何 Bourne-like 或-like 或fish
shell中均有效。 And 表示/path/to/grep
使用grep
, foo
and file
inargv[]
和LC_ALL=C
in运行envp[]
(shell 位于execve(file, argv[], envp[])
系统调用的所有接口之前)。
then
因此,解析器接受并识别该标记作为/构造then
的关键字并不完全令人惊讶,因为在任何需要命令的地方都需要这样做。if
fi
then
您还会发现您可以执行以下操作:
if then else (echo foo) fi
出于同样的原因。
但我不会依赖它,因为它没有记录并且将来可能会改变。
在if true then
or中if echo then
,显然是/ 的then
参数,并且该结构缺少它的。true
echo
if
then
实际上,POSIX 不允许then
将其识别为关键字(在语法中)。var='value'
sh
POSIX 要求:
var=value keyword
keyword
不被识别为关键字,但作为要执行的命令的名称并不太有用,尽管没有人会在 POSIX shell 关键字之后命名命令。
例如,POSIX 要求:
var=value if true
if
如果可以true
作为参数并var=value
在其环境中运行该命令,则运行该命令。
$ ln -s /bin/printenv bin/if
$ a=bar bash -c 'if a'
bash: -c: line 1: syntax error: unexpected end of file
$ bash -c 'a=foo if a'
foo
$ zsh -c 'a=foo if a'
zsh:1: parse error near `if'
zsh 不遵循该要求(即使在sh
模拟中)不太可能在实践中引起问题。我希望在不太可能发生的情况下,任何人想要调用名为 的命令if
,他们会编写它'if'
or "if"
or\if
以避免它被误认为是if
关键字,无论它前面是否有var=value
and/或 重定向。
$ a=bar bash -c '"if" a'
bar
$ bash -c 'a=foo "if" a'
foo
$ a=bar zsh -c '"if" a'
bar
$ zsh -c 'a=foo "if" a'
foo
附带说明一下,POSIX 要求:
if true; then if true; then echo x; fi fi
(这两个之间没有换行符或分号fi
)才能工作,这是一个奇怪的要求,但它只是指定了 ksh88 所做的事情(继承自 Bourne shell),这是 POSIX 规范主要基于的实现。
zsh
不遵守该要求,它不允许在 后添加额外的单词fi
。
if (true) then (echo x) fi
适用于大多数 shell,包括zsh
,但 IIRC 在这种情况下,POSIX 未指定该行为。
1 事实上,作为一个历史轶事,早期的 Unices 有一个名为 的命令if
。那是在 Bourne shell 或 C shell 出现之前,后来它们有了自己的if
构造。然后将其删除,因为这些结构是多余的。