一次通过管道传输完整的数组对象而不是数组项?

2024-01-12

如何将一个 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 ?


脚注

  1. 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 一次处理数组中的每个数组,并且输入中的每个子数组的内容都将作为一个对象处理,即使它是一个数组。


简短回答:使用一元数组运算符,:

,$theArray | foreach{Write-Host $_}

长答案:有件事你应该明白@()运算符:它总是将其内容解释为语句,即使内容只是一个表达式。考虑这段代码:

$a='A','B','C'
$b=@($a;)
$c=@($b;)

我添加了明确的语句结束标记;在这里,尽管 PowerShell 允许省略它。$a是三个元素的数组。什么结果$a;陈述?$a是一个集合,因此应枚举集合,并且应通过管道传递每个单独的项目。所以结果是$a;语句是写入管道的三个元素。@($a;)看到这三个元素,但不是原始数组,并从它们创建数组,所以$b是三个元素的数组。同样的方式$c是相同三个元素的数组。所以当你写的时候@($collection)您创建数组,复制元素$collection,而不是单个元素的数组。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

一次通过管道传输完整的数组对象而不是数组项? 的相关文章

随机推荐