Конвейер Powershell “разворачивает” коллекции ради удобства пользователей и, забавно сказать, ради “единообразия”. Унарный оператор запрещает powershell это разворачивание. Те примеры не самые удачные, попробую зайти с другой стороны.
Посмотрите на вывод двух фрагментов
(4, 5, 6) | ForEach-Object {
Write-Host "Pipeline element now: $_"
}
Pipeline element now: 4
Pipeline element now: 5
Pipeline element now: 6
,(4, 5, 6) | ForEach-Object {
Write-Host "Pipeline element now: $_"
}
Pipeline element now: 4 5 6
Во втором вся коллекция передаётся целиком как один объект, поэтому разворачивания не происходит. Это массив, а пробелы вместо запятых появляются из-за стандартного разделителя полей вывода, которым служит пробел (он хранится в $ofs). Это можно увидеть так
"$(4, 5, 6)"
4 5 6
Когда массив встраивается в строку, powershell соединяет его элементы стандартным OFS. Изменить его можно, хотя нужно это редко.
$ofs = '/~/'
"$(4, 5, 6)"
4/~/5/~/6
Один из довольно частых для меня случаев применения унарного оператора: разбить значения, но при этом передать все элементы вместе одним объектом.
,(-split 'Tavin enjoys powershell') | ForEach-Object {
[PSCustomObject]@{
Who = $_[0]
Does = $_[1]
Topic = $_[2]
}
}
Who Does Topic
--- ---- -----
Tavin enjoys powershell
Переведено с английского·Показать оригиналThe Powershell pipeline “unwraps” collections for convenience and, amusingly, for user “consistency”. That unary operator stops powershell from performing that unwrapping. Those examples aren't ideal, so I'll try another approach.
Look at what these two snippets produce
(4, 5, 6) | ForEach-Object {
Write-Host "Pipeline element now: $_"
}
Pipeline element now: 4
Pipeline element now: 5
Pipeline element now: 6
,(4, 5, 6) | ForEach-Object {
Write-Host "Pipeline element now: $_"
}
Pipeline element now: 4 5 6
The latter sends the complete collection through as a single object, so it never gets unwrapped. It's an array, and the spaces you see, rather than commas, come from the space used as the default output field separator (held in $ofs). Here's a way to observe that
"$(4, 5, 6)"
4 5 6
Embedding that array in a string makes powershell join its elements using the default OFS. Changing it is possible, although seldom necessary.
$ofs = '/~/'
"$(4, 5, 6)"
4/~/5/~/6
One fairly frequent use for that unary operator in my own work is splitting values while keeping every element together in a single object.
,(-split 'Tavin enjoys powershell') | ForEach-Object {
[PSCustomObject]@{
Who = $_[0]
Does = $_[1]
Topic = $_[2]
}
}
Who Does Topic
--- ---- -----
Tavin enjoys powershell