Powershell,使用(space 分隔的)字符串作为程序的参数

Powershell, use (space-separated) string as arguments to a program

我已阅读 但它没有解决我的问题。

我有一个 space 分隔的字符串,比方说 $MyString = "arg1 arg2"。假设我有一个名为 MyProgram 的命令行程序,它接受任意数量的位置参数,因此它可以像 MyProgram arg1 arg2 一样 运行。但是 MyProgram $MyString 不起作用,MyProgram ($MyString -split ' ')MyProgram $($MyString -split ' ') 也不起作用。我得到同样的错误,基本上说它不识别参数“arg1 arg2”,我猜这是因为它仍然认为它是一个包含 space 的参数而不是两个参数。实际上,$MyString 可能非常大并且是从文件中读取的。我该怎么做?

哦,我刚刚发现如何大声笑。我早该想到这一点;基本上,只需使用 splatting 以下对我有用:

$MyArray = $($MyString -split " ")
MyProgram @MyArray

解释:第一行将字符串转换为由space(" ")分割的字符串数组;命令周围的 $(...) 符号捕获命令的输出,然后我将其分配给 $MyArray。然后,我没有将 $MyArray 与美元符号 $ 一起使用,而是将其与 @ 一起使用,将字符串数组拼成 MyProgram.

的参数

这些对我有用($args 已保留)。 -split 在左侧拆分为空白。或者您可以从文件中获取内容,其中每个参数都在单独的一行上。您可能 运行 限制了命令行的长度。将该列表通过管道传输或从文件中加载可能是更好的方法。

echo hi > file.txt

$args2 = 'hi','file.txt'
findstr $args2
# hi

$args2 = 'hi','file.txt'
& findstr $args2
# hi

$args2 = 'hi file.txt'
findstr (-split $args2)
# hi

findstr ($args2 -split ' ')
# hi

tl;dr

对于调用PowerShell命令你确实需要splatting才能通过 数组的元素 作为 个人,位置 参数 ;这需要在 辅助变量 中定义数组,然后可以使用 sigil @ 代替 $ 传递以请求展开:

$myArray = -split $myString   # See below for limitations, bottom section for fix
MyPowerShellCommand @myArray  # Array elements are passed as indiv. arguments.

虽然此技术也适用于 外部程序,但它并不是绝对必要的,您可以直接传一个数组达到同样的效果:

MyExternalProgram (-split $myString) # Array elements are passed as indiv. args.

请注意,(...) 而不是 $(...) 用于将表达式作为参数传递。 (...) 通常就足够了,通常更可取,因为 $(...) 可能有副作用 - 详情请参阅


只是为了把 and 放在一起:

首先,需要明确的是:由于仅按 空格 进行拆分,这两个答案都无法正确处理参数列表字符串中具有 嵌入空格的参数(因此,有必要使用 嵌入式引号 ),例如,$myString = "arg1 `"arg2 with spaces`" arg3" 不会按预期工作 - 请参阅底部的解决方案。

撇开这个不谈,区别是:

  • 调用外部程序时,如链接post、传递一个数组导致每个元素成为它自己的参数.

    • 也就是说,myExternalProgram (-split $MyString) 可以。
    • 请注意,我使用 -split operator 一元 形式进行更灵活的标记化,它被 任何非空 运行 的空格 同时忽略前导和尾随空格(与 awk 的默认行为相同)。
  • 当调用 PowerShell 命令 时, 数组由默认通过原样,作为一个整体,作为单个参数.

    • 要达到与外部程序相同的效果,即 将数组的元素作为单独的位置参数传递,您确实必须使用 splatting,即您必须:

      • 首先将数组保存在变量中:$myArray = -split $myString,
      • 然后你可以通过使用 @ 而不是 $ 作为印记将其作为 splatted 参数传递: MyPowerShellCommand @myArray
    • 请注意 在调用 PowerShell 命令时 它比 使用 hashtable- 而不是基于数组的展开 ,因为它 允许您通过名称 显式绑定到参数 而不是按位置 - PowerShell 命令通常具有可以 按名称绑定的参数。

      • 例如,如果 MyPowerShellCommand 接受参数 -Foo-Bar,您可以使用:
        $myArgs = @{ Foo='foo value'; Bar='bar value '}; MyPowerShellCommand @myArgs

如果您确实想要处理参数列表字符串,这些字符串的参数带有 嵌入式引号:

$myString = 'arg1 "arg2 with spaces" arg3'

$myArray = (Invoke-Expression ('Write-Output -- ' + $myString -replace '$', "`0")) -replace "`0", '$$'

注意:,但在这个特定命令中采取的额外预防措施使其使用安全。

$myArray 是一个包含逐字元素 arg1arg2 with spacesarg3 的 3 元素数组,可以再次如上所示使用。

有关该技术的说明,请参阅