我尝试通过管道将字符串数组传输到write-host,并显式使用$_
写入这些字符串:
'foo', 'bar', 'baz' | write-host $_
但是,它失败的原因是:
- 无法将输入对象绑定到命令的任何参数,因为命令不接受管道输入,或者输入及其属性与接受管道输入的任何参数都不匹配。*
这个错误消息对我来说毫无意义,因为我完全能够编写
'foo', 'bar', 'baz' | write-host
我本以为这两条管道是等效的。显然,它们不是。那么,有什么区别呢?
我尝试通过管道将字符串数组传输到write-host,并显式使用$_
写入这些字符串:
'foo', 'bar', 'baz' | write-host $_
但是,它失败的原因是:
这个错误消息对我来说毫无意义,因为我完全能够编写
'foo', 'bar', 'baz' | write-host
我本以为这两条管道是等效的。显然,它们不是。那么,有什么区别呢?
3条答案
按热度按时间kh212irz1#
左,右
$_
变量及其 * 别名 *$PSItem
仅在特定上下文中 * 在脚本块 *({ ... }
)**内具有有意义的值。我本以为两条管线是等效的。
他们不是:
'foo', 'bar', 'baz' | write-host
它是以下管道等效物(最终效果等效,而非技术等效):
也就是说,在您的命令中,
Write-Host
从管道接收输入,该管道 * 隐式地 * 绑定到其-Object
参数 * 用于每个输入对象 *,这是由于参数-Object
被声明为经由属性[Parameter(ValueFromPipeline=$true)]
接受管道输入'foo', 'bar', 'baz' | write-host $_
$_
)绑定到参数 * first *:因为
$_
前面没有参数名,所以它在 * 位置上 * 绑定到-implied--Object
参数。然后,当流水线处理开始时,* 流水线 * 参数绑定发现没有流水线绑定
Write-Host
参数要再绑定到,假定唯一这样的参数-Object
* 已经被绑定 ,即通过 * 自变量 *$_
。换句话说: * 命令错误地尝试绑定
-Object
参数 * 两次 *; * * 不幸的是,错误消息并没有明确说明这一点。更重要的一点是,**使用
$_
只在脚本块 *({ ... }
)**内有意义,该脚本块 *({ ... }
)**为每个输入对象 * 计算 *。在该上下文之外,
$_
(或其别名$PSItem
)通常没有值,不应使用-请参阅底部部分以了解所有上下文的概述,在这些上下文中,脚本块中的$_
/$PSItem
得到了有意义的支持。虽然
$_
最常用于传递给ForEach-Object
和Where-Object
cmdlet的脚本块中,但还有其他有用的应用程序,最常使用Rename-Item
cmdlet:a delay-bind script-block argument:也就是说,不是向
Rename-Item
传递一个 * static * 新名称,而是传递一个 * script块,该块针对每个输入对象 * 进行求值(输入对象通常绑定到$_
),从而启用动态行为。然而,如链接答案中所解释的,该技术仅对(a)流水线绑定和(b)* 非 *
[object]
或[scriptblock]
类型化的参数起作用;因此,假定Write-Object
的-Object
参数 * 是 *[object]
类型的,则该技术 * 不 * 工作:因此,在这种情况下,基于管道的解决方案需要使用
ForEach-Object
:有意义地定义
$_
(及其别名$PSItem
)的上下文:这些上下文的共同之处在于,
$_
/$PSItem
引用必须在script block({ ... }
)内进行,也就是说,一个传递给*/在中使用:ForEach-Object
和Where-Object
小命令;例如:.ForEach()
和内部.Where()
方法;例如:switch
语句中的条件和相关脚本块;例如:function
和filters
;例如:Register-ObjectEvent
调用的-Action
参数的脚本块);例如::对Santiago Squarzon的提示。[ValidateScript()]
属性;注意,对于 * array * 值参数,脚本块被称为 * for each element *;例如,-replace
运算符的替换操作数;例如:<ScriptBlock>
元素的上下文中(但在基于脚本块的ETS成员的上下文中 * 不是 *,其中改用$this
)。.InvokeWithContext()
等 * PowerShell SDK方法 * 的上下文中eoxn13cs2#
您可以像iRon在注解中所指示的那样使用它。
$_
或$PSItem
是正在处理的管道中的当前对象。通常,您会在需要处理块或脚本块的命令中看到这一点。您必须将Write-Host
命令包含在类似的处理块中。下面是使用函数的进程块的示例:
waxmsbnn3#
$_在脚本块之外 * 永远 * 不会工作。用write-output代替怎么样: