zsh:命令替换和正确引用

use*_*428 5 zsh

我有一个P接受文件名作为参数的脚本:

P file1 file2 file3 ....
Run Code Online (Sandbox Code Playgroud)

我还有一个脚本G,它生成文件名(通常是短列表),每行一个文件名。在我想用zsh编写的主脚本中,我想用G它来生成要由P. 天真的尝试是这样的:

P $(G)
Run Code Online (Sandbox Code Playgroud)

这几乎很有效,只是我生活在一个恶意的人喜欢创建带有嵌入空间的文件的世界中。如果G会生成这样的文件列表:

one_file 
a file with spaces
Run Code Online (Sandbox Code Playgroud)

P将被称为

P one_file a file with spaces
Run Code Online (Sandbox Code Playgroud)

代替

P 'one_file' 'a file with spaces'
Run Code Online (Sandbox Code Playgroud)

一个明显的解决方案是将G和粘合P在一起,不是通过命令替换,而是通过某种语言(Ruby、Perl、Python、Algol68,....)的小程序,该程序执行P并将参数传递给读取标准输入。

这编写起来很简单,甚至可以重用。然而,我想知道,zsh及其各种好东西是否没有内置的解决方案来解决这个问题?

Ada*_*hon 5

这可以通过以下方式实现:

P ${(f)"$(G)"}
Run Code Online (Sandbox Code Playgroud)

这将P称为

P 'one_file' 'a file with spaces'
Run Code Online (Sandbox Code Playgroud)

如果 的输出G

one_file
a file with spaces
Run Code Online (Sandbox Code Playgroud)

解释:

周围的双引号$(G)告诉zsh将 的输出G作为一个单词(在单词 word 的 shell 意义上)。

所以只是打电话

P "$(G)"
Run Code Online (Sandbox Code Playgroud)

将相当于

P 'one_file
a file with spaces'
Run Code Online (Sandbox Code Playgroud)

这就是参数扩展标志 f发挥作用的地方。${(f)SOMEVAR}告诉zsh在换行符处分割成$SOMEVAR单词。除了参数(如SOMEVAR)之外,还可以在类型参数表达式中使用命令替换(此处$(G)${...},这会导致命令P ${(f)"$(G)"}