【发布时间】:2015-04-30 16:35:21
【问题描述】:
如何将一个 CmdLet 的输出作为一个完整的数组对象发送到管道中的下一个 CmdLet,而不是一次一个地发送数组中的单个项?
问题 - 一般描述
正如在about_pipelines (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 一次处理一个,输入的每个子数组的内容即使是一个数组也被视为一个对象。
【问题讨论】:
-
Powershell 展开数组。在这个网站和其他地方有关于这个的讨论。展开很奇怪,但这意味着您不能
@(@(@()))并获得多个数组(大致)。 -
请提出一个问题。删除所有其他无关的东西(这些都与您的原始问题无关)并且您的原始问题是您最少解释的问题。将输出包装在
@()中不起作用吗? -
我同意@EtanReisner,这很难理解。如果您有多个问题,请分别发布。即使一些支持示例重叠,最好这样做。同样如前所述,powershell 展开数组。它还试图强制比较的右侧,这就是为什么交换对象可以给你不同的结果。
-
你想做什么?
"A", "B", "C" | Format-Custom -Expand CoreOnly证明您正在将整个阵列推送到Format-Customcmdlt,那么您想要什么? -
澄清、阐述和具体化问题
标签: arrays powershell object syntax pipeline