zsh 无法保持未加引号的 `$*` 和 `$@` 相等

zsh 无法保持未加引号的 `$*` 和 `$@` 相等

所有测试的 shell 都使用以下代码对(引用的)“$*”和“$@”对执行相同的操作:

c='set a b @ c; IFS=:,@ ; a=$(printf "<%s> " "$*"); b=$(printf "<%s> " "$@"); printf "%-20s and %-20s\n" "$a" "$b"'

d=(sh ash dash attsh ksh lksh mksh bash b44sh y2sh zsh zsh4 "zsh -y")
for shell in "${d[@]}"; do
    printf '%15s: ' "$shell"
    $shell -c "$c"
done

结果:

         sh: <a:b:@:c>            and <a> <b> <@> <c>     
        ash: <a:b:@:c>            and <a> <b> <@> <c>     
       dash: <a:b:@:c>            and <a> <b> <@> <c>     
      attsh: <a:b:@:c>            and <a> <b> <@> <c>     
        ksh: <a:b:@:c>            and <a> <b> <@> <c>     
       lksh: <a:b:@:c>            and <a> <b> <@> <c>     
       mksh: <a:b:@:c>            and <a> <b> <@> <c>     
       bash: <a:b:@:c>            and <a> <b> <@> <c>     
      b44sh: <a:b:@:c>            and <a> <b> <@> <c>     
       y2sh: <a:b:@:c>            and <a> <b> <@> <c>     
        zsh: <a:b:@:c>            and <a> <b> <@> <c>     
       zsh4: <a:b:@:c>            and <a> <b> <@> <c>     
     zsh -y: <a:b:@:c>            and <a> <b> <@> <c> 

但是,对于未引用的$*$@测试(只$c需要更改):

c='set a b @ c; IFS=:,@ ; a=$(printf "<%s> " $*); b=$(printf "<%s> " $@); printf "%-20s and %-20s\n" "$a" "$b"'

结果是:

         sh: <a> <b> <> <> <c>    and <a> <b> <> <> <c>   
        ash: <a> <b> <> <> <c>    and <a> <b> <> <> <c>   
       dash: <a> <b> <> <> <c>    and <a> <b> <> <> <c>   
      attsh: <a> <b> <> <c>       and <a> <b> <> <c>      
        ksh: <a> <b> <> <c>       and <a> <b> <> <c>      
       lksh: <a> <b> <> <> <c>    and <a> <b> <> <> <c>   
       mksh: <a> <b> <> <> <c>    and <a> <b> <> <> <c>   
       bash: <a> <b> <> <> <c>    and <a> <b> <> <> <c>   
      b44sh: <a> <b> <> <> <c>    and <a> <b> <> <> <c>   
       y2sh: <a> <b> <> <> <c>    and <a> <b> <> <> <c>   
        zsh: <a> <b> <@> <c>      and <a> <b> <@> <c>     
       zsh4: <a> <b> <@> <c>      and <a> <b> <@> <c>   
     zsh -y: <a> <b> <> <> <c>    and <a> <b> <@> <c>  

撇开 ksh 中删除重复值不谈,除了 zsh 之外,所有 shell 的行为方式都是相同的。其中呈现了一个@.如果默认情况下引用变量(或者默认情况下不执行拆分),这可能是合理的。

但是在尝试获取所有其他 shell 的默认值并要求 zsh 拆分(取消引用)所使用的变量时,我们得到了不同的值$*$@

再次更改$c为:

c='set a b @ c; IFS=:,@ ; a=$(printf "<%s> " $*); b=$(printf "<%s> " $@); [ "$a" = "$b" ] && echo "Yes" || echo "Nope"'

我们得到这个明确的结果:

         sh: Yes
        ash: Yes
       dash: Yes
      attsh: Yes
        ksh: Yes
       lksh: Yes
       mksh: Yes
       bash: Yes
      b44sh: Yes
       y2sh: Yes
        zsh: Yes
       zsh4: Yes
     zsh -y: Nope

只有 zsh 没有不带引号(分割)$*$@等于。

答案1

那是一个漏洞(回归)在zsh-4.3.11-dev-4版本中引入2011 年,现在由这个变更集

该修复现已包含在 5.3 版本(2016 年 12 月 11 日发布)及更高版本中。该错误影响版本 4.3.11-dev-4 至 5.2。

相关内容