zsh中的变量扩展与bash中的变量不同

Shr*_*rat 13 bash shell zsh

以下是我想要说明的简单测试用例.

在bash,

# define the function f
f () { ls $args; }

# Runs the command `ls`
f

# Runs the fommand `ls -a`
args="-a"
f

# Runs the command `ls -a -l`
args="-a -l"
f
Run Code Online (Sandbox Code Playgroud)

但在zsh

# define the function f
f () { ls $args }

# Runs the command `ls`
f

# Runs the fommand `ls -a`
args="-a"
f

# I expect it to run `ls -a -l`, instead it gives me an error
args="-a -l"
f
Run Code Online (Sandbox Code Playgroud)

上面zsh中的最后一行给出了以下错误

ls: invalid option -- ' '
Try `ls --help' for more information.
Run Code Online (Sandbox Code Playgroud)

我认为zsh正在执行

ls "-a -l"
Run Code Online (Sandbox Code Playgroud)

这是我得到同样的错误.

那么,我如何在这里获得bash的行为?

我不确定我是否清楚,如果你想知道什么,请告诉我.

Chr*_*sen 30

不同之处在于(默认情况下)zsh不会对未加引号的参数扩展进行单词拆分.

您可以通过设置SH_WORD_SPLIT选项或=在单个扩展上使用标志来启用"正常"单词拆分:

ls ${=args}
Run Code Online (Sandbox Code Playgroud)

要么

setopt SH_WORD_SPLIT
ls $args
Run Code Online (Sandbox Code Playgroud)

如果您的目标shell支持数组(ksh,bash,zsh),那么最好使用数组:

args=(-a -l)
ls "${args[@]}"
Run Code Online (Sandbox Code Playgroud)

来自zsh FAQ:

zsh手册:

  • 14.3参数扩展

    特别要注意的是,除非设置了选项SH_WORD_SPLIT,否则不带引号参数的单词不会自动在空白上拆分; 有关详细信息,请参阅下面对此选项的引用.这是与其他炮弹的重要区别.

  • SH_WORD_SPLIT

    导致在不带引号的参数扩展上执行字段拆分.

  • 我所有版本的*bash*(3.2.48和4.2.10)都拒绝`$ {= ...}`.我很确定它是否特定于*zsh*.如果您的目标是*bash*和*zsh*,那么您可以尝试一个数组(在我更新的答案中). (4认同)