Я бы ожидал, что оба конвейера будут эквивалентны.
Это не так:
'foo', 'bar', 'baz' | write-host
Это основанный на конвейере эквивалент следующего (эквивалент по конечному эффекту, а не технически):
foreach ($str in 'foo', 'bar', 'baz') { Write-Host -Object $str }
То есть в вашей команде Write-Host
получает входные данные из конвейера, который неявно привязывается к его -Object
параметр для каждого входного объекта , в силу того, что параметр -Object
объявлен как принимающий вход конвейера через атрибут [Parameter(ValueFromPipeline=$true)]
'foo', 'bar', 'baz' | write-host $_
Перед началом конвейерной обработки аргументы - $_
в вашем случае - связаны с параметрами first :
Поскольку $_
не предшествует имя параметра, он связывает позиционно с - подразумеваемым - -Object
параметром.
Затем, когда начинается конвейерная обработка, pipe *Параметр 1045 * привязки не находит параметр привязки к конвейеру Write-Host
, к которому больше привязываться, учитывая, что единственныйтакой параметр, -Object
уже был связан , а именно аргументом $_
.
Другими словами: ваша команда по ошибке пытается связатьпараметр -Object
дважды ; к сожалению, сообщение об ошибке не совсем ясно дает понять.
Большее значение в том, что с использованием $_
только когда-либо делаетсмысл внутри блока скрипта ({ ... }
) , который оценивается для каждого входного объекта .
Вне этого контекста, $_
(или его псевдоним, $PSItem
) обычно не имеет значения и не должен использоваться.
Хотя $_
чаще всего используется в блоках сценария, передаваемых в командлеты ForEach-Object
и Where-Object
, существует другое полезное приложение, чаще всегообычно встречается с командлетом Rename-Item
: аргумент блока сценария с задержкой привязки :
# Example: rename *.txt files to *.dat files using a delay-bind script block:
Get-Item *.txt | Rename-Item -NewName { $_.BaseName + '.dat' }
То есть вместо передачи статического нового имени вRename-Item
, вы передаете блок скрипта, который оценивается для каждого входного объекта - с указателем входного объектаот d до $_
, как обычно - что обеспечивает динамическое поведение.
Как объяснено в связанном ответе, однако, этот метод работает только с параметрами, которые являются (a) привязкой к конвейеру и (b) не [object]
или [scriptblock]
напечатано;поэтому, учитывая, что Write-Object
-Object
параметр напечатан [object]
, метод не работает:
# Try to enclose all inputs in [...] on output.
# !! DOES NOT WORK.
'foo', 'bar', 'baz' | write-host -Object { "[$_]" }
Следовательно, конвейеррешение на основе требует использования ForEach-Object
в этом случае:
# -Object is optional
PS> 'foo', 'bar', 'baz' | ForEach-Object { write-host -Object "[$_]" }
[foo]
[bar]
[baz]