Expresión Lambda en Powershell

Tengo un código en C# que usa expresiones lambda para pasar delegados a un método. ¿Cómo puedo lograr esto en PowerShell. Por ejemplo, el siguiente es un código C#:

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);

Y este es el script de PowerShell sin la expresión lambda en su lugar:

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

Nota: mi pregunta no se trata de resolver este problema de expresión regular. Solo quiero saber cómo pasar una expresión lambda a un método que recibe delegados en PowerShell.

preguntado el 12 de junio de 12 a las 12:06

3 Respuestas

En PowerShell 2.0 puede usar un bloque de script ({ some code here }) como delegado:

$MatchEvaluator = 
{  
  param($m) 

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

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

O directamente en la llamada al método:

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

Consejos:

Puede usar el [regex] para convertir una cadena en una expresión regular:

$r = [regex]"\((?<val>[\,\!\;\:])\)"
$r.Matches(...)

Respondido el 12 de junio de 12 a las 12:06

Y gracias también por mencionar el param($m) sintaxis dentro de los bloques de script. - Sina Iravanian

Si alguien quisiera un ejemplo real: $repo.Deployments.FindOne({ param($d) $d.EnvironmentId -eq $envId }); - Joe Phillips

A veces solo quieres algo como esto:

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

(que declarará una 'función' anónima y la llamará inmediatamente).

Respondido el 21 de junio de 13 a las 22:06

Puedes usar esta sobrecarga

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

El delegado se pasa como un scriptblock (expresión lambda) y se puede acceder a MatchEvaluator a través de la variable $args

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

Respondido el 12 de junio de 12 a las 12:06

¿Puedes usar un ScriptBlock en lugar de cualquier delegado? ¿Dónde está documentado esto? - usuario189198

En términos generales, sí. No tengo conocimiento de ninguna documentación. - shay levy

Gracias esto funciona. Y +1 por mencionar el $args matriz dentro del bloque de script. - Sina Iravanian

¡Gracias! Alternativamente, puede definir parámetros con nombre con la palabra clave param. - shay levy

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.