我下载了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技术,您可以在其中指定要通过变量传递给命令的参数:
  • 两种(通常情况下,仅用于外部程序):
  • 作为参数的数组,分别作为位置参数传递,如上所示。
  • 或(通常在调用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/

    10-12 00:18
    查看更多