如何将一个 CmdLet 的输出作为完整的数组对象发送到管道中的下一个 CmdLet,而不是一次发送一个数组中的各个项目?
问题 - 通用描述
正如在帮助中可以看到的关于管道 https://technet.microsoft.com/en-us/library/hh847902.aspx (help pipeline
) powershell 在管道中一次发送一个对象。所以Get-Process -Name notepad | Stop-Process
同时将一个进程发送到管道中。
假设我们有一个无法以任何方式修改或更改的第 3 方 CmdLet (Do-SomeStuff)。如果传递字符串数组或传递单个字符串对象,Do-SomeStuff 的执行会有所不同。
Do-SomeStuff 只是一个例子,它可以替换为ForEach-Object
, Select-Object
, Write-Host
(或任何其他接受管道输入的 CmdLet)
在此示例中,Do-SomeStuff 将一次处理数组中的各个项目。
$theArray = @("A", "B", "C")
$theArray | Do-SomeStuff
如果我们想将完整的数组作为一个对象发送给 Do-SomeStuff,可以尝试这样的操作
@($theArray) | Do-SomeStuff
但它不会产生预期的结果,因为 PowerShell“忽略”新的单项数组。
那么,如何“强行”呢?$theArray
作为单个数组对象而不是当时的内容项沿着管道传递?
问题-实际例子
如下图所示的输出Write-Host
如果传递一个数组或一次传递数组中的各个项目,则情况会有所不同。
PS C:\> $theArray = @("A", "B", "C")
PS C:\> Write-Host $theArray
A B C
PS C:\> $theArray | foreach{Write-Host $_}
A
B
C
PS C:\> @($theArray) | foreach{Write-Host $_}
A
B
C
你要怎样做才能得到$theArray | foreach{Write-Host $_}
产生相同的输出Write-Host $theArray
?
脚注
- Powershell 中的管道处理
一个普通的字符串数组
PS C:\> @("A", "B", "C").GetType().FullName
System.Object[]
通过管道传输到 Foreach-Object 的普通字符串数组
PS C:\> @("A", "B", "C") | foreach{$_.GetType().FullName}
System.String
System.String
System.String
ForEach-Object CmdLet 一次处理数组中的每个字符串。
数组的数组,其中“内部”数组是字符串数组。
PS C:\> @(@("A", "B", "C"), @("D", "E", "F"), @("G", "H", "I")) | foreach{$_.GetType().FullName}
System.Object[]
System.Object[]
System.Object[]
ForEach-Object CmdLet 一次处理数组中的每个数组,并且输入中的每个子数组的内容都将作为一个对象处理,即使它是一个数组。