Как вы отправляете вывод из одного CmdLet в следующий в конвейере как полный массив-объект вместо отдельных элементов в массиве по одному за раз?
Проблема - Общее описание
Как видно из справки about_pipelines (help pipeline
), powershell отправляет объекты по одному вниз по конвейеру¹. Таким образом, Get-Process -Name notepad | Stop-Process
отправляет один процесс во время работы по трубе.
Предположим, что у нас есть сторонний 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
Каждая строка в массиве обрабатывается по одному в тот момент, когда объект-объект CmdLet ForEach-Object.
Массив массивов, где "внутренние" массивы представляют собой массивы строк.
PS C:\> @(@("A", "B", "C"), @("D", "E", "F"), @("G", "H", "I")) | foreach{$_.GetType().FullName}
System.Object[]
System.Object[]
System.Object[]
Каждый массив в массиве обрабатывается по одному в тот момент, когда объект CmdLet ForEach-Object, и содержимое каждого подматрица от входа обрабатывается как один объект, даже если это массив.