我有一个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及其各种好东西是否没有内置的解决方案来解决这个问题?
这可以通过以下方式实现:
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)"}。