3

I'm having some difficulty finding a "native" powershell -replace call that would replace a match with something based on the match. E.g. in perl it would be like this:

my %definedVars = ( ab => "hello", cd => "there" );
my $str = q"$(ab) $(cd)";
$str =~ s/\$\(([^)]+)\)/$definedVars{$1}/ge;
print "$str\n";

I was thinking that in powershell, it'd be something like this:

$definedVars = @{ ab = 'hello'; cd = 'there' }
'$(ab) $(cd)' -replace "\$\(([^)]+)\)", { $definedVars[$1] }

I've looked around and I think that the -replace switch doesn't have an deferred evaluator, so I'd have to use the .NET replace function, but I'm not entirely sure how that works. I'm thinking it would be something like this:

$definedVars = @{ ab = 'hello'; cd = 'there' }
[regex]::replace('$(ab) $(cd)',
   "\$\(([^)]+)\)",
   { $definedVars[$_.Groups[1].Value] } )

Documentation is sparse, so if you could also state where you got your info from, that would be great.

Adrian
  • 10,246
  • 4
  • 44
  • 110

1 Answers1

2

Looks like it is just a syntax problem. I have to specify the parameter and use that. $_ is not defined as a special default parameter. So it would be like this:

$definedVars = @{ ab = 'hello'; cd = 'there' }
[regex]::replace('$(ab) $(cd)',
   "\$\(([^)]+)\)",
   { param($m); $definedVars[$m.Groups[1].Value] } )

Edit

As mjolinor pointed out, instead of defining the params, I could use $args array instead, like this:

$definedVars = @{ ab = 'hello'; cd = 'there' }
[regex]::replace('$(ab) $(cd)',
   "\$\(([^)]+)\)",
   { $definedVars[$args[0].Groups[1].Value] } )

This is slightly better if I'm only referencing that parameter once, but if the delegate gets more complex, IMO it would still be better to use param to specify the parameters.

Adrian
  • 10,246
  • 4
  • 44
  • 110
  • This is correct; you have to define a parameter for the script block and use that to receive each match. – briantist Nov 13 '15 at 15:06
  • I got the syntax from [Powershell how to create a delegate](http://stackoverflow.com/a/19850707/1366368). – Adrian Nov 13 '15 at 15:11
  • You don't have to define the parameter. You can use $args -> [regex]::replace('$(ab) $(cd)', "\$\(([^)]+)\)", { $definedVars[$args[0].Groups[1].Value] } ) – mjolinor Nov 13 '15 at 15:13
  • It would have been nice if the native `-replace` had a evaluation syntax. – Adrian Nov 13 '15 at 15:13
  • @mjolinor, I had tried `$args` before and couldn't get it working. Thanks for the reminder. – Adrian Nov 13 '15 at 15:17