我看到 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/*
我本来希望最后一个命令像在 bash 中那样扩展。知道我做错了什么吗?
那将是我第一次看到有人抱怨这一点(我们更经常看到人们抱怨它没有在参数扩展时进行分词)。
大多数人都期待
输出
$file
变量的内容并在 shellbash
不输出时感到恼火(从 Bourne shell 继承的行为,不幸的是没有被 ksh 修复并由 POSIX 为sh
解释器指定),这导致了很多错误和安全漏洞和这就是为什么您需要引用这些 shell 中的所有变量。参见例如:忘记在 bash/POSIX shells 中引用变量的安全隐患
我看到你在写作时也期待这一点,
echo $0
而不是echo "$0"
。zsh
已经解决了。默认情况下,它在参数扩展时既不通配也不分词。您需要明确要求:echo $=file
: 执行分词echo $~file
:执行通配符echo $=~file
: 两者都执行或者您可以打开
globsubst
andshwordsplit
选项以获得与 Bourne-like shell 中相同的行为(这两个选项在zsh
被调用时启用以sh
实现sh
兼容性),但我不建议您这样做,除非您需要zsh
解释为另一个 shell 编写的代码(甚至在这种情况下,sh
使用 ) 在本地上下文中的仿真中解释该代码会更有意义emulate -L sh
。file
在这里命名你的变量如果您打算在扩展时扩展它,则会产生误导¹
会更有意义。如果你想要一个变量保存当前目录中所有非隐藏文件的名称,你会这样做:
或者:
如果当前目录中没有非隐藏文件,则该分配不会失败。
也就是说,使用数组变量赋值。那 ( ) 与or , or
file=(*)
中的工作方式相同,只是它没有 Bourne shell 的其他错误特征,即当没有匹配时模式不展开。bash
ksh93
mksh
yash
zsh
¹请注意,这
*
是类 Unix 系统上文件的完全有效名称。我感到有些欣慰的是,即使该文件被调用,它也会rm -f -- $file
删除存储其名称的文件。$file
*