我下载了npm软件包以合并junit报告-https://www.npmjs.com/package/junit-merge。
问题是我有多个文件要合并,并且我试图使用字符串变量来保存要合并的文件名。
当我编写脚本myslef时,如下所示:
junit-merge a.xml b.xml c.xml
这有效,正在创建合并文件,但是当我这样做时
$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的行为不像bash
这样的POSIX shell 程序那样:在bash
中,变量$command
的值(由于未引用而引起的)将受到分词(所谓的shell expansions)的影响导致3个不同的参数(尽管最好是基于数组的调用)。
PowerShell不支持类似于bash
的shell扩展[2];它具有不同的,通常更灵活的构造,例如下面讨论的splatting技术。
相反,将您的参数定义为数组的各个元素,如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技术,您可以在其中指定要通过变量传递给命令的参数:
$
替换变量引用中的@
标记;例如,在您的情况下@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
被调用。此问题同样会影响基于数组的展开,因此
$cmdArgs = "", "other"; foo.exe $cmdArgs
生成foo.exe other
而不是预期的foo.exe "" other
。与基于数组的一起可选地使用
@
:您也可以将
@
标记符与数组一起使用,因此也可以使用:junit-merge @command
但是,有一个细微的区别。
在实践中,这几乎无关紧要,
较为安全的选择是使用
$
,因为它可以防止(无论是假设性的)意外误解您打算成为文字的--%
数组元素。仅
@
语法将数组元素--%
识别为特殊的stop-parsing symbol, --%
该符号告诉PowerShell不要像通常那样解析其余的参数,而是按原样传递它们,除了扩展
cmd.exe
样式的变量引用(例如%USERNAME%
)外。通常,这仅在不使用喷溅时才有用,通常是在能够按原样使用PowerShell中为
cmd.exe
编写的命令行的情况下,而无需考虑PowerShell的语法差异。但是,在进行喷溅时,由
--%
引起的行为是不明显的,最好避免:--%
从结果命令行中删除。 foo bar
放置的单个数组元素"foo bar"
被作为foo bar
放置,即有效地作为2个参数。 [1]您的调用意味着打算将变量
$command
的值作为单个参数传递,因此,当PowerShell在幕后构建命令行时,它将双引号a.xml b.xml c.xml
中包含的逐字$command
字符串以确保这一点。请注意,这些双引号与最初为$command
分配值的方式无关。不幸的是,这种自动报价被嵌入的
"
chars破坏了。 -例如,参见this answer。[2]为了表示类似POSIX的 shell ,PowerShell确实执行了一种 shell 扩展,但是(a)仅在类似Unix的平台(macOS,Linux)上,并且(b)仅在调用外部程序时:无引号的通配符模式,例如因为当您调用外部程序(例如
*.txt
)时,/bin/echo *.txt
确实扩展为它们的匹配文件名,PowerShell调用了本地globlob的功能。关于powershell - 在PowerShell中使用变量将多个参数传递给外部程序,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/59069918/