在zsh中,变量展开与bash不同。

32

下面是我想展示的一个简单测试用例。

在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

但是在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

在上面的zsh中,最后一行代码给我返回了以下错误信息

ls: invalid option -- ' '
Try `ls --help' for more information.

我认为zsh正在执行

ls "-a -l"

这就是我遇到相同错误的情况。那么,我该如何在这里获得bash的行为呢?

我不确定我的表述是否清楚,请让我知道您需要了解的内容。


3
这不是回答你的问题,但我认为这更好:f () { ls "$@"; }; f -a -l,意思是定义一个函数 f,然后调用该函数并传递参数 -a-lls 命令。 - glenn jackman
@glenn,是的,绝对是这样的。正如我所说,这只是我面临的一个更大问题的例证,我必须使用args变量。 - sharat87
2
@ShrikantSharat 如果你正在编写bash、zsh(和ksh)脚本,请不要使用args变量,而应该使用数组。 - Gilles 'SO- stop being evil'
1个回答

61

区别在于(默认情况下),zsh不会对未使用引号的参数展开进行单词分割。

您可以通过设置SH_WORD_SPLIT选项或在单个展开上使用=标志来启用“普通”单词分割:

ls ${=args}

或者

setopt SH_WORD_SPLIT
ls $args

如果你的目标shell支持数组(kshbashzsh),那么最好使用数组:

args=(-a -l)
ls "${args[@]}"

来自zsh FAQ:

来自zsh手册:

  • 14.3 参数扩展

    特别要注意的是,除非设置了选项 SH_WORD_SPLIT,否则未引用的参数的单词不会自动拆分为多个单词;有关该选项的更多详细信息,请参阅下面的引用。这是与其他Shell的一个重要区别。

  • SH_WORD_SPLIT

    导致未引用的参数扩展被分割成多个字段。


是的,这正是我想要的。我不知道该在哪里搜索或查找,您能指向一些解释这个问题的文档吗?感谢您的回答。 - sharat87
4
我所有版本的 bash (3.2.48 和 4.2.10) 都无法识别 ${=…}。我很确定这是 zsh 特有的。如果你的目标是 bashzsh,那么你可以尝试使用数组(在我的更新答案中)。 - Chris Johnsen
对,它不起作用。我正在检查 zsh 并在子 shell 中使用 SH_WORD_SPLIT 选项。我希望可以使用数组,但我必须使用一个变量 :) - sharat87

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接