59

I have a code in C# which uses lambda expressions for delegate passing to a method. How can I achieve this in PowerShell. For example the following is a C# code:

string input = "(,)(;)(:)(!)";
string pattern = @"\((?<val>[\,\!\;\:])\)";
var r = new Regex(pattern);
string result = r.Replace(input, m =>
    {
        if (m.Groups["val"].Value == ";") return "[1]";
        else return "[0]";
    });
Console.WriteLine(result);

And this is the PowerShell script without the lambda-expression in place:

$input = "(,)(;)(:)(!)";
$pattern = "\((?<val>[\,\!\;\:])\)";
$r = New-Object System.Text.RegularExpressions.Regex $pattern
$result = $r.Replace($input, "WHAT HERE?")
Write-Host $result

Note: my question is not about solving this regular-expression problem. I just want to know how to pass a lambda expression to a method that receives delegates in PowerShell.

3 Answers 3

79

In PowerShell 2.0 you can use a script block ({ some code here }) as delegate:

$MatchEvaluator = 
{  
  param($m) 

  if ($m.Groups["val"].Value -eq ";") 
  { 
    #... 
  }
}

$result = $r.Replace($input, $MatchEvaluator)

Or directly in the method call:

$result = $r.Replace($input, { param ($m) bla })

Tip:

You can use [regex] to convert a string to a regular expression:

$r = [regex]"\((?<val>[\,\!\;\:])\)"
$r.Matches(...)
Sign up to request clarification or add additional context in comments.

2 Comments

And thanks also for mentioning the param($m) syntax inside the script-blocks.
If anyone would like a real example: $repo.Deployments.FindOne({ param($d) $d.EnvironmentId -eq $envId });
33

Sometimes you just want something like this:

{$args[0]*2}.invoke(21)

(which will declare an anonymous 'function' and call it immediately.)

Comments

18

You can use this overload

[regex]::replace(
   string input,
   string pattern, 
   System.Text.RegularExpressions.MatchEvaluator evaluator
)

The delegate is passes as a scriptblock (lambda expression) and the MatchEvaluator can be accessed via the $args variable

[regex]::replace('hello world','hello', { $args[0].Value.ToUpper() })

4 Comments

Can you use a ScriptBlock in place of any delegate? Where is this documented?
Generally speaking, yes. I'm not aware of any documentation.
Thanks this works. And +1 for mentioning the $args array inside the script block.
Thanks! Alternatively you can define named parameters with the param keyword.

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.