什么有用 -
假设我有一个scriptblock
,我使用Select-Object
cmdlet。
$jobTypeSelector = `
{
if ($_.Type -eq "Foo")
{
"Bar"
}
elseif ($_.Data -match "-Action ([a-zA-Z]+)")
{
$_.Type + " [" + $Matches[1] + "]"
}
else
{
$_.Type
}
}
$projectedData = $AllJobs | Select-Object -Property State, @{Name="Type"; Expression=$jobTypeSelector}
这很好用,我得到了预期的结果。
我想做什么 -
但是,在稍后的代码中,我想重复使用定义为scriptblock
的{{1}}。
例如,我希望下面的代码能够将$jobTypeSelector
(请注意它是单个对象)作为下面的参数传递,并用于$fooJob
自动变量$_
并返回相同的结果,因为它在scriptblock
cmdlet的上下文中执行时返回。
Select-Object
什么行不通 -
它没有按照我的预期工作,我得到了空值。
我已尝试过的内容 -
我查了一下,所有属性都已正确设置,并且不是由于相关属性本身为空或$fooType = $jobTypeSelector.Invoke($fooJob)
。
我在互联网上看了一下,似乎很难找到关于这个主题的任何相关页面,但我最终找到一个接近在稍微不同的背景下解释问题的页面 - {{ 3}}。博客没有直接回答我的问题,任何相关的解释只会导致我认为非常难看,难以阅读和维护的解决方案。
问题 -
那么,为{strong>单个对象调用$null
的最佳方法是什么,该方法使用scriptblock
自动变量作为参数,而不是$_
块)
答案 0 :(得分:4)
在摆弄varoius选项之后,我最终以一种Hackish的方式解决问题..但我发现它是最好的解决方案,因为它很小,易于阅读,维护和理解。
即使我们讨论的是单个对象,也要在管道中使用它(PowerShell
定义$_
自动变量时)ForEach-Object
cmdlet
$fooType = $fooJob | ForEach-Object $jobTypeSelector
答案 1 :(得分:1)
当你提到时,你当然可以使用foreach
或ForEach-Object
。
如果通过将IsFilter
设置为$true
将其从函数ScriptBlock更改为过滤器 ScriptBlock,您也可以直接传递给ScriptBlock:
$jobTypeSelector.IsFilter = $true
$fooType = $fooJob | $jobTypeSelector
但是,更好的是如果您使用命名函数而不是匿名ScriptBlock,例如:
function Get-JobType
{
Param (
[object] $Job
)
if ($Job.Type -eq "Foo")
{
"Bar"
}
elseif ($Job.Data -match "-Action ([a-zA-Z]+)")
{
$Job.Type + " [" + $Matches[1] + "]"
}
else
{
$Job.Type
}
}
然后您可以将其与Select-Object
又名select
一起使用,如下所示:
$projectedData = $AllJobs |
select -Property State, @{Name="Type"; Expression={Get-JobType $_}}
或者只有一份工作,如下:
$fooType = Get-JobType $fooJob