使用PowerShell中的变量将多个参数传递给外部程序

问题描述 投票:1回答:1

我下载了用于合并junit报告的npm软件包-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

这不起作用。错误是

错误:找不到文件

有人遇到过类似的问题吗?

powershell junit parameter-passing parameter-splatting
1个回答
1
投票

$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中,由于引用了[[unquoted

,变量$command的值将为-受到word splitting(所谓的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技术的应用程序,在其中您指定要通过

variable

传递给命令的参数。
    两者之一(通常只用于
  • external program
,如您的情况):

作为参数的[[[[[[array]

,分别作为
    位置参数
传递,如上所示。
  • 或者(通常在调用PowerShell命令时使用:):
  • 作为

      hashtable

  • 传递
  • named
  • 参数值,其中您必须

    $替换变量引用中的@标记

    ;例如,在您的情况下为@command;例如,以下等效于调用Get-ChildItem C:\ -Directory$paramVals = @{ LiteralPath = 'C:\'; Directory = $true }; Get-ChildItem @paramVals
  • 基于数组的注意事项] ::
  • 由于this GitHub issue中详细描述的错误,


    PowerShell不会将

    empty参数传递给外部程序(从Windows PowerShell 5.1 / PowerShell [Core] 7.0开始仍然适用)为了保持向后兼容)。例如,foo.exe ""意外导致仅调用foo.exe

    此问题同样会影响基于数组的展开,因此$cmdArgs = "", "other"; foo.exe $cmdArgs产生foo.exe other,而不是预期的foo.exe "" other

    @与基于数组的拼写的可选使用

    您也可以将@标记与


    arrays一起使用,因此也可以使用:

    junit-merge @command

    但是有一个细微的区别。

    尽管在实践中这几乎无关紧要,更安全的选择是使用$

    ,因为它可以防止(不管是假想的)对要成为
    literal
    --%数组元素的误解。

    @语法将数组元素--%识别为特殊的stop-parsing symbol, --%

    [该符号告诉PowerShell不要像往常一样解析其余参数,而是按原样传递它们-未扩展,除了扩展--%样式的变量引用,例如cmd.exe

    这通常仅在使用[使用splatting时有用,通常在能够使用原样从PowerShell中为%USERNAME%编写的命令行的上下文中,而不必考虑PowerShell的语法差异。 >但是,在

    splatting

    中,由cmd.exe引起的行为是不明显的,最好避免:

    直接传递参数时,--%已从结果命令行中

    删除

    • [参数边界丢失,因此通常在命令行上作为--%放置的单个数组元素foo bar被放置为"foo bar",即有效地被放置为

      2] >参数。

  • [[1]您的电话暗示打算将变量foo bar的值作为单个参数

    传递,因此,当PowerShell在幕后构建命令行时,它将双引号$command括起来。确保a.xml b.xml c.xml中包含的字符串。请注意,这些双引号与您最初为$command分配值的方式无关。不幸的是,对于带有嵌入式$command字符的值,此自动报价无效。 -例如,请参见"

  • [2]作为对类似POSIX的外壳的致敬,PowerShell

    does

    执行一种外壳扩展,但仅在类似Unix的平台(macOS,Linux)上:不带引号的通配符模式,例如this answer确实在您调用外部程序(例如*.txt)时扩展为它们匹配的文件名,PowerShell调用native globlob。
    © www.soinside.com 2019 - 2024. All rights reserved.