变量中的全局字符在 bash 中扩展,但在 zsh 中不扩展

Bru*_*son 4 zsh wildcards variable-substitution

我看到 zsh 的一个问题,其中变量中的 glob 字符没有像我预期的那样扩展。下面的例子可以更好地解释它。

$ echo $0
-bash

$ echo $HOME/Downloads/zsh-test/*
/Users/bruce/Downloads/zsh-test/file1 /Users/bruce/Downloads/zsh-test/file2 /Users/bruce/Downloads/zsh-test/file3 /Users/bruce/Downloads/zsh-test/file4

$ file=*; echo $HOME/Downloads/zsh-test/$file
/Users/bruce/Downloads/zsh-test/file1 /Users/bruce/Downloads/zsh-test/file2 /Users/bruce/Downloads/zsh-test/file3 /Users/bruce/Downloads/zsh-test/file4

Macbook% echo $0
zsh

Macbook% echo $HOME/Downloads/zsh-test/*
/Users/bruce/Downloads/zsh-test/file1 /Users/bruce/Downloads/zsh-test/file2 /Users/bruce/Downloads/zsh-test/file3 /Users/bruce/Downloads/zsh-test/file4

Macbook% file=*; echo $HOME/Downloads/zsh-test/$file
/Users/bruce/Downloads/zsh-test/*
Run Code Online (Sandbox Code Playgroud)

我原以为最后一个命令会像在 bash 中那样扩展。知道我做错了什么吗?

Sté*_*las 14

那将是我第一次看到有人抱怨这个(我们更经常看到人们抱怨它没有在参数扩展时进行分词)。

大多数人期待

echo $file
Run Code Online (Sandbox Code Playgroud)

输出$file变量的内容并且当 shell 像bash不一样时感到恼火(从 Bourne shell 继承的行为,不幸的是没有被 ksh 修复并由 POSIX 为sh解释器指定),这导致了很多错误和安全漏洞和这就是为什么您需要引用这些 shell 中的所有变量的原因。

例如,请参阅:忘记在 bash/POSIX shell 中引用变量的安全隐患

我看到您在写作时也期待这一点,echo $0而不是echo "$0"

zsh已经解决了。默认情况下,它在参数扩展时既不进行通配也不进行分词。您需要明确请求这些:

  • echo $=file: 进行分词
  • echo $~file: 执行通配
  • echo $=~file: 两者都执行

或者您可以打开globsubstshwordsplit选项以获得与类似 Bourne 的 shell 相同的行为(为了兼容性zsh而调用这两个选项时启用这两个选项),但我不建议这样做,除非您需要解释为另一个 shell 编写的代码(即使在这种情况下,在本地上下文中模拟解释该代码也会更有意义)。shshzshshemulate -L sh

这里命名您的变量file

file=*
Run Code Online (Sandbox Code Playgroud)

如果您打算在扩展时扩展它,则具有误导性¹

filename_pattern=*
Run Code Online (Sandbox Code Playgroud)

会更有意义。如果你想要一个变量来保存当前目录中所有非隐藏文件的名称,你可以这样做:

files=(*)
Run Code Online (Sandbox Code Playgroud)

或者:

files=(*(N))
Run Code Online (Sandbox Code Playgroud)

如果当前目录中没有非隐藏文件,则该分配不会失败。

即,使用数组变量赋值。该 ( file=(*)) 与bashor ksh93, mkshor 中的工作方式相同yash,只是它zsh没有 Bourne shell 的其他错误特征,即在没有匹配项时不展开模式。


¹请注意,*对于类 Unix 系统上的文件来说,这是一个完全有效的名称。我感到有些欣慰rm -f -- $file的是,$file即使该文件被称为*.