更新时间:2022-11-12 15:46:35
延迟绑定脚本块参数是 隐式 >功能:
Delay-bind script-block arguments are an implicit feature that:
仅与旨在接受管道输入的参数一起使用 ,
only works with parameters that are designed to take pipeline input,
任何类型的除了以下,在这种情况下会发生常规参数绑定 [1] :
[scriptblock]
[object]
(但是,[psobject]
起作用,因此[pscustomobject]
也起作用)[object]
[scriptblock]
[object]
([psobject]
, however, does work, and therefore [pscustomobject]
too)[object]
这些参数是否接受通过 value (ValueFromPipelineBy
)或通过属性名称(ValueFromPipelineByPropertyName
)进行的管道输入.
whether such parameters accept pipeline input by value (ValueFromPipelineBy
) or by property name (ValueFromPipelineByPropertyName
), is irrelevant.
通过脚本块传递的代替类型合适的自变量每个输入对象 ;将为每个管道对象评估脚本块,该脚本块通常可以在$_
中以$_
的形式在脚本块内部进行访问,并且假定脚本块的 output -假定其与参数类型相符-用作参数.
enables per-input-object transformations via a script block passed instead of a type-appropriate argument; the script block is evaluated for each pipeline object, which is accessible inside the script block as $_
, as usual, and the script block's output - which is assumed to be type-appropriate for the parameter - is used as the argument.
由于按照定义,此类临时脚本块与您要定位的参数类型不匹配,因此在传递它们时必须始终显式使用参数名称.
延迟绑定脚本块无条件提供对管道输入对象的访问,即使该参数通常不受给定的管道对象绑定,如果它定义为ValueFromPipelineByPropertyName
,并且该对象缺少该名称的属性.
Delay-bind script blocks unconditionally provide access to the pipeline input objects, even if the parameter would ordinarily not be bound by a given pipeline object, if it is defined as ValueFromPipelineByPropertyName
and the object lacks a property by that name.
Rename-Item
的调用之类的技术,其中,通常将Get-Item
的管道输入绑定到-LiteralPath
参数,但是将脚本块传递给-NewName
-通常仅绑定到具有.NewName
属性的输入对象-启用对同一管道对象的访问,从而从输入文件名派生目标文件名:
Get-Item file | Rename-Item -NewName { $_.Name + '1' } # renames 'file' to 'file1'
;输入绑定到 -LiteralPath
(隐式)和 -NewName
脚本块.Rename-Item
, where the pipeline input from Get-Item
is - as usual - bound to the -LiteralPath
parameter, but passing a script block to -NewName
- which would ordinarily only bind to input objects with a .NewName
property - enables access to the same pipeline object and thus deriving the destination filename from the input filename:
Get-Item file | Rename-Item -NewName { $_.Name + '1' } # renames 'file' to 'file1'
; input binds to both -LiteralPath
(implicitly) and the -NewName
script block.注意:例如,与传递给ForEach-Object
或Where-Object
的脚本块不同,延迟绑定脚本块在 child 变量范围内运行 [2] ,这意味着您不能直接修改调用者的变量,例如在输入对象之间增加计数器.
解决方法是,使用在调用方作用域中声明的[ref]
类型变量,并在脚本块内访问其.Value
属性-请参见这个答案为例.
Note: Unlike script blocks passed to ForEach-Object
or Where-Object
, for example, delay-bind script blocks run in a child variable scope[2], which means that you cannot directly modify the caller's variables, such as incrementing a counter across input objects.
As a workaround, use a [ref]
-typed variable declared in the caller's scope and access its .Value
property inside the script block - see this answer for an example.
[1]错误条件:
如果您错误地尝试将脚本块传递给不是管道绑定或[scriptblock]
-或[object]
类型(未键入)的参数, 常规参数绑定:
If you mistakenly attempt to pass a script block to a parameter that is either not pipeline-binding or is [scriptblock]
- or [object]
-typed (untyped), regular parameter-binding occurs:
[object]
或[scriptblock]
的参数/可以转换为脚本块的委托类型(例如System.Func
),脚本块将按原样绑定 .[string]
类型的参数,脚本块的文字内容作为字符串值传递.[object]
or [scriptblock]
/ a delegate type such as System.Func
that is convertible to a script block, the script block will bind as-is.[string]
-typed parameter, the script block's literal contents is passed as the string value.如果您忽略提供管道输入,而将延迟绑定脚本块传递给支持的管道绑定参数,则会得到以下错误:
If you neglect to provide pipeline input while passing a delay-bind script block to a pipeline-binding parameter that does support them, you'll get the following error:
Cannot evaluate parameter '<name>' because its argument is specified as a script block and there is no input. A script block cannot be evaluated without input.
[2]此差异正在此GitHub问题中进行讨论