if var='value' then in Zsh: 这真的是一个没有分号的有效语法吗?

if var='value' then in Zsh: 这真的是一个没有分号的有效语法吗?

以下代码适用于我尝试过的 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 或fishshell中均有效。 And 表示/path/to/grep使用grep, fooand fileinargv[]LC_ALL=Cin运行envp[](shell 位于execve(file, argv[], envp[])系统调用的所有接口之前)。

then因此,解析器接受并识别该标记作为/构造then的关键字并不完全令人惊讶,因为在任何需要命令的地方都需要这样做。iffithen

您还会发现您可以执行以下操作:

if then else (echo foo) fi

出于同样的原因。

但我不会依赖它,因为它没有记录并且将来可能会改变。

if true thenor中if echo then,显然是/ 的then参数,并且该结构缺少它的。trueechoifthen

实际上,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=valueand/或 重定向。

$ 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构造。然后将其删除,因为这些结构是多余的。

相关内容