我想创建一个枚举一些数据的PowerShell函数,并在所有情况下触发脚本块。
到目前为止,我已经有了(这不是实际的代码,但是它说明了我的问题):
function Invoke-TenTimes
{
[CmdletBinding()]
param
(
[Parameter(Mandatory=$true, Position=0)]
[ScriptBlock]$Action
)
process
{
$digits = 0..10
$digits | % {
$Action.Invoke($_);
}
}
}
我将此功能放在模块中。但是,致电时我没有得到任何结果:
Invoke-TenTimes { $_ }
输出为空白(不显示任何内容)。
如果我打电话
Invoke-TenTimes { $_ -eq $null }
我得到十个
true
。实际上,我看到$_
为null。填充
$_
的正确方法是什么?使我发疯的是,如果我将此函数和调用放在同一个ps1文件中,则可以正常工作(但我想按需传递脚本块):
function Invoke-TenTimes
{
[CmdletBinding()]
param
(
[Parameter(Mandatory=$true, Position=0)]
[ScriptBlock]$Action
)
process
{
$digits = 0..10
$digits | % {
$Action.Invoke($_);
}
}
}
Invoke-TenTimes { $_ }
最佳答案
这是一个范围问题,因为传入的脚本块与执行范围不同。如果传入的脚本块不必从其上下文中引用变量,则可以简单地克隆脚本块以强制其位于您正在运行的范围内。与
$action = [scriptblock]::Create($action)
有趣的是,它仅在事故发生时才起作用。它是从脚本块所属的父范围中获取了$ _,恰好在您的foreach-object内部,这很好。
但是使用您的原始版本,然后运行
"gotcha" | % {
Invoke-TenTimes { $_ }
}
并且您会看到获得10次提示,因为$ _在您的调用方作用域中不是null,而是某种东西。