How to use expression in regex -replace with capturing group in powershell

50 views Asked by At

I want to replace octal codes with the ascii character equivalents in a string.

Input example: \052.test.com

I've tried all sorts of different combinations, but why doesn't this work, and how do I fix it?

> "\052.test.com" -replace '\\(0[1-7][0-7])', "`$1"
052.test.com

> "\052.test.com" -replace '\\(0[1-7][0-7])', [char][convert]::ToInt32("052", 8)
*.test.com

> "\052.test.com" -replace '\\(0[1-7][0-7])', [char][convert]::ToInt32("`$1", 8)
MethodInvocationException: Exception calling "ToInt32" with "2" argument(s): "Could not find any recognizable digits."
1

There are 1 answers

3
Mathias R. Jessen On BEST ANSWER

In Windows PowerShell, the second right-hand argument to -replace will be evaluated like any other expression, and the resulting argument value treated as a string no matter what you pass to it.

To invoke a callback function against each match, you can use [regex]::Replace(...), and pass a scriptblock in place of the substitution string - the runtime will pass a MatchInfo object as the first argument to the scriptblock, from where you can extract the capture groups value:

[regex]::Replace("\052.test.com", '\\0([0-7][0-7])', {
  $matchInfo = $args[0]
  [convert]::ToInt32($matchInfo.Groups[1].Value, 8) -as [char]
})

In PowerShell 6.2+ and 7 you can pass the scriptblock directly as an operand to -replace - the MatchInfo result will be bound to $_ automatically:

"\052.test.com" -replace '\\0([0-7][0-7])', {
  [convert]::ToInt32($_.Groups[1].Value, 8) -as [char]
}