# WRONG
$command = "a.xml b.xml c.xml"; junit-merge $command
导致命令行junit-merge "a.xml b.xml c.xml"[1],即它将字符串a.xml b.xml c.xml 作为单个参数 传递给junit-merge,这不是本意。
PowerShell 不在这方面表现得像 POSIX-like shell,例如 bash:在 bash 中,变量 $command 的值 - 由于被引用 未引用 - 会受到 分词(所谓的shell expansions 之一)的影响,并且确实会导致 3 个不同的参数(尽管即使存在基于数组的调用也会更好) .
PowerShell 不支持类似bash 的外壳扩展[2];它具有不同的、通常更灵活的构造,例如下面讨论的喷溅技术。
相反,将您的参数定义为数组的单个元素,正如justnotme 建议的那样:
# Define the *array* of *individual* arguments.
$command = "a.xml", "b.xml", "c.xml"
# Pass the array to junit-merge, which causes PowerShell
# to pass its elements as *individual arguments*; it is the equivalent of:
# junit-merge a.xml b.xml c.xml
junit-merge $command
这是一种称为splatting 的 PowerShell 技术的应用程序,您可以在其中指定要通过变量传递给命令的参数:
-
要么(通常仅用于外部程序,如您的情况):
-
作为一个数组作为位置参数单独传递的参数,如上所示。
-
或者(更常见的是在调用 PowerShell 命令时):
-
作为哈希表来传递命名参数值,您必须在其中替换变量引用中的$ sigil @;例如,在你的情况下@command;例如,以下相当于调用Get-ChildItem C:\ -Directory:
-
$paramVals = @{ LiteralPath = 'C:\'; Directory = $true }; Get-ChildItem @paramVals
警告基于数组的喷溅:
由于this GitHub issue 中详述的错误,PowerShell 不会将 空 参数传递给外部程序(从 Windows PowerShell 5.1 / PowerShell [Core ] 7.0,并且可能永远不会更改以保持向后兼容性)。
例如,foo.exe "" 意外导致只调用了 foo.exe。
此问题同样会影响基于数组的 splatting,因此
$cmdArgs = "", "other"; foo.exe $cmdArgs 会产生 foo.exe other 而不是预期的 foo.exe "" other。
可选使用 @ 和基于数组的 splatting:
您也可以将@ 印记与数组一起使用,所以这也可以:
junit-merge @command
但是有一个微妙的区别。
虽然在实践中很少有影响,
更安全的选择是使用$,因为它可以防止(无论假设如何)意外误解您打算成为一个文字的--% 数组元素。
只有@ 语法将数组元素--% 识别为特殊的stop-parsing symbol, --%
该符号告诉 PowerShell 不要像通常那样解析剩余的参数,而是按原样传递它们 - 未扩展,除了扩展 cmd.exe 样式的变量引用,例如 %USERNAME%。
这通常仅在不使用 splatting 时有用,通常是在能够按原样使用 PowerShell 为 cmd.exe 编写的命令行的上下文中,而无需考虑 PowerShell 的语法差异。
然而,在 splatting 的上下文中,--% 导致的行为并不明显,最好避免:
[1] 您的调用意味着将变量 $command 的值作为 单个参数 传递的意图,因此当 PowerShell 在后台构建命令行时,它会使用双引号$command 中包含的逐字 a.xml b.xml c.xml 字符串以确保这一点。请注意,这些双引号与您最初为$command 分配值的方式无关。
不幸的是,对于嵌入了 " 字符的值,这种自动引用被破坏了。 - 例如,参见this answer。
[2] 作为对类 POSIX shell 的致敬,PowerShell 确实 执行一种 shell 扩展,但 (a) 仅在类 Unix 平台(macOS、Linux)和(b) 仅在调用外部程序时:当您调用外部程序(例如,/bin/echo *.txt)时,不带引号的通配符模式(例如 *.txt)确实会扩展为它们的匹配文件名,这是 PowerShell 调用 native globbing.