zsh (vs. bash) 参数膨胀异常

zsh (vs. bash) parameter expansion anomaly

如果执行脚本

X=abcd
echo ${1:-$X}
echo ${1?$X}

不传任何参数,在bash下做,输出

abcd
./mrh.sh: line 3: 1: abcd

如果你运行它在zsh下,它输出

abcd
mrh.sh:3: 1: -$X

我们看到在 ${...?...} 的情况下,替换 ($X) 在 bash 下展开,但在 zsh 下没有。在 ${...:-...} 的情况下,$X 在 bash 和 zsh.

中都被扩展

我查阅了 zsh 手册页以找到解释,为什么在第二种情况下没有替换 $X,但找不到任何内容。是 zsh 的 bug 吗?

使用 zsh 5.0.6

解释实际上可以在zsh (zshexpn(1)) and bash (bash(1)).

的手册页中找到

对于两个 shell,替换的文本也受参数扩展的约束:

  • zshexpn(1):

    […] the replacement text of any substitutions, are themselves subject to parameter expansion […]

  • bash(1):

    In each of the cases below, word is subject to tilde expansion, parameter expansion […]

以下是有问题的替换的相关部分(我强调):

  1. 对于 ${1:-$X} 两个 shell 的行为相同:

    • zshexpn(1):

      ${name:-word}

      If name is […] is non-null, then substitute its value; otherwise substitute word.

    • bash(1):

      ${parameter:-word}

      […] If parameter is unset or null, the expansion of word is substituted. Otherwise, the value of parameter is substituted

    虽然 zsh 联机帮助页没有明确提到 word 再次扩展,但上述规则涵盖了这一点。导致在您的示例中打印 abcd

  2. 对于${1:?$X}zsh的措辞略有不同:

    • zshexpn(1):

      ${name:?word}

      [...] if name is both set and non-null, then substitute its value; otherwise, print word and exit from the shell.

    • bash(1):

      ${parameter:?word}

      If parameter is null or unset, the expansion of word [...] is written to the standard error and the shell, if it is not interactive, exits. Otherwise, the value of parameter is substituted.

    对于bash明确表示word展开。但是对于 zsh 它声明 word 被打印而不是被替换。这也意味着它不受上述规则的约束。