Warren Stevens
Warren Stevens

Reputation: 1057

How to pass operator to a function in Powershell

I have some Powershell code that looks like the following:

if($item_1 -lt 2000000){
  ...
}
if($item_2 -lt 10000){
  ...
}
if($item_3 -gt 10){            
  ...
}
if($item_4 -gt 100){
  ...          
}

I'd like to refactor it into a function like

function doComparison( $item, $operator, $value)

but I'm not sure how I can pass the less-than and greater-than operators to the function. One solution would be to pass the operator as text (e.g. "-lt") and then have an if statement in the function, but that is inelegant. Is there a better way to do this?


I'm accepting the reply from "user2460798" as "Invoke-Expression" is the concept I previously did not know about (i.e. being able to "assemble code on the fly").

My code now looks like what I was originally hoping for:

checkLine $item_1 lt 2000000
checkLine $item_2 lt 10000
checkLine $item_3 gt 10
checkLine $item_4 gt 100

Thanks for the responses, everyone!

Upvotes: 1

Views: 848

Answers (3)

Χpẘ
Χpẘ

Reputation: 3451

You can use Invoke-Expression. Kind of like this:

function doComparison( $item, $operator, $value) {
  # Notice the dash here. Example: doComparsion $item_4 lt 150
  # If you try to implement it where the dash is specified on the command line
  #  (doComparision $item_4 -lt 150) then PS will treat -lt as a parameter name.
  iex "($item) -$operator ($value)"   
}

But there may be be some additional tweaking necessary to take care of cases where $item and/or $value is an expression, but the parenthesis should handle common cases.

Upvotes: 2

zdan
zdan

Reputation: 29450

You could pass a scriptblock as an argument to doComparison:

function doComparison($item, [scriptblock]$comp, $value)
{
    if(invoke-command -scriptblock $comp -arg $item,$value)
    {
        "It's true"
    }
    else
    {
        "It's false"
    }
}

and call it like this:

doComparison 2 {$args[0] -lt $args[1]} 1000

Though this doesn't seem very "elegant". But perhaps if you predefine a bunch of sciptblocks:

$lt = {$args[0] -lt $args[1]}
$gt = {$args[0] -gt $args[1]}

it's closer to what you're after:

# > doComparison 2 $lt 1000
It's true

# > doComparison 2 $gt 1000
It's false

Upvotes: 3

mjolinor
mjolinor

Reputation: 68301

I don't know of a more "elegant" way to pass and apply the operator, but I'd consider creating a custom Enum for the operators to constain the values that can be passed, and enable tab-completion for the parameter value.

Upvotes: 1

Related Questions