2

I'm trying to figure out a way to incorporate a filter into a custom function and I haven't been able to get it working:

Function Test-Me{
    Param
    (
      $Filter = "Number -like ""Three"""
    )

    $Obj = New-Object PSObject -Properties &{
                                             Number = "One","Two","Three"
                                            }

    If($Filter){
     $Obj | Where-Object $Filter
    }else{
     $Obj
    }
}

I've tried various means, but they all fail:

$Filter = 'Where-Object{$_' + $Filter + '}'
$Obj | & $Filter

.

$Filter = "Number -like ""One"""
$Obj | Where & $Filter

How do you incorporate Filter support into custom functions?

2 Answers 2

3

Set the parameter type to ScriptBlock:

Function Test-Me {
  Param(
    [ScriptBlock]$Filter = {$_.Number -like 'Three'}
  )

  $Obj = 'One','Two','Three' | % {[PSCustomObject]@{Number = $_}}
  $Obj | Where-Object $Filter
}

and define the filters as actual scriptblocks:

PS C:\> Function Test-Me {
>>   Param([ScriptBlock]$Filter = {$_.Number -like 'Three'})
>>   $Obj = 'One','Two','Three' | % {[PSCustomObject]@{Number = $_}}
>>   $Obj | Where-Object $Filter
>> }
>>
PS C:\> Test-Me

Number
------
Three

PS C:\> $sb = { $_.Number -like 't*' }
PS C:\> Test-Me $sb

Number
------
Two
Three

PS C:\> Test-Me {$_.Number -like '*e'}

Number
------
One
Three

If your function must accept string input for some reason you could create scriptblocks from the strings, as @Richard suggested:

Function Test-Me {
  Param(
    [string]$Filter = '$_.Number -like "Three"'
  )

  $fltr = [ScriptBlock]::Create($Filter)

  $Obj = 'One','Two','Three' | % {[PSCustomObject]@{Number = $_}}
  $Obj | Where-Object $fltr
}
Sign up to request clarification or add additional context in comments.

2 Comments

You don't actually have to include the $_ with your filter. But this is the closest to a real answer so I'll accept yours.
@Colyn1337 The simplified syntax only works for simple expressions and only in PowerShell v3 and newer. If for instance you want to combine 2 or more conditions with logical operators ($_.Number -like 't*' -or $_.Number -like '*e') you must use $_.
1

You cannot just pass a string and expect it to be expanded as the cmdlet's parameters: PowerShell's parsing is more sophisticated than that.

But you should be able to convert a string into a script block (for example, see here). Then pass the script block to Where-Object's -FilterScript parameter.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.