3

I'm trying to get a Where-Object FilterScript scriptblock into a variable, but I have had no luck far. As a simple example of what I'm trying to do:

$test = @('one','two','three')
$filter = '$_ -eq "one"'
$test | Where-Object -FilterScript { $filter }

This doesn't seem to work; I get back all elements. I've also tried:

$filter = { $_ -eq "one" }
$filter = [scriptblock]::Create($_ -eq 'one')

These all return:

one
two
three

However, replacing the variable with the actual filter works as expected:

$test | Where-Object -FilterScript { $_ -eq "one" }

This returns only "one", without "two" and "three". Does anyone know how I can make this work? I was originally trying it on Core v7.0.3, but tested on Windows PowerShell v5.1 as well.

2
  • 1
    i don't think you can do that. the $_ var is not defined outside of the pipeline, so your script block becomes [null] -eq 'one'.
    – Lee_Dailey
    Commented Sep 11, 2020 at 4:11
  • I was starting to get that impression. I was hoping to pass the filter in to a function that would then work with the items that the filter matched. My workaround at the moment is to do the filtering outside the function and pass the filtered list in. I'll hold on to hope that someone knows better and can help, but I fear you're right.
    – DarkMoon
    Commented Sep 11, 2020 at 4:15

1 Answer 1

5

The curly braces after -FilterScript are messing you up, once the variable contains a ScriptBlock you don't need those braces anymore. If you have them there, it's a scriptblock of a variable containing a scriptblock.

$foo = "hi"
$foo | gm     (TypeName: String)
{$foo} | gm   (TypeName: ScriptBlock)

If you add [scriptblock] to your $filter variable to strongly type the variable, it complains about the formatting until you add the braces when you define your variable. This is a great way to ensure the object you're feeding Where-Object matches the expected type for its -FilterScript parameter which is ScriptBlock

It will work without the strong type being forced once the braces are in the variable definition, which causes it to become a ScriptBlock, but I'd leave the type in there so the engine complains if somebody removes the braces and doesn't realize they're changing your variable type in the process.

$test = @('one','two','three')
[scriptblock]$filter = { $_ -eq "one" }
$test | Where-Object -FilterScript $filter
one
1
  • Well I'll be damned. I had assumed that [scriptblock]::Create would automatically make it a scriptblock (i.e., put the { and } in), but updating to [scriptblock]::Create({ $_ -eq 'one }) worked. Thanks!
    – DarkMoon
    Commented Sep 14, 2020 at 11:54

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .