-
Notifications
You must be signed in to change notification settings - Fork 8.1k
Description
Wishful thinking:
# Script block as replacement operand allows dynamic substitutions.
# TBD: how to refer to the match at hand in the script block.
> 'Increment these numbers: 1 2 3' -replace '\d+', { [int] $Args.Value + 1 }
Increment these numbers: 2 3 4Sometimes string replacements need to be dynamic, i.e., the replacement string must be derived from the match at hand.
Consider the following (contrived example):
You want to increment all numbers in an input string; e.g.:
'Increment these numbers: 1 2 3' -> 'Increment these numbers: 2 3 4'
Currently, -replace doesn't support this type of replacement, because the replacement operand can only statically refer to the match at hand ($& for the match in full, $1 for the 1st capture group's match (if any), ...).
Thus, to achieve this kind of substitution the .NET Framework must currently be used:
> [regex]::Replace('Increment these numbers: 1 2 3', '\d+', { param($match) [int] $match.Value + 1 })
Increment these numbers: 2 3 4Needless to say, this is neither PowerShell-like nor simple.
Supporting the syntax as proposed at the top would greatly simplify such operations.
Syntax details
The simplest approach is to use [regex]::Replace() as-is behind the scenes, and let the script block reference the match at hand - which is passed as a [System.Text.RegularExpressions.Match] instance - via $Args (or, optionally, an explicitly defined parameter via param()).
The alternative is to stick with the $&, $1, ... syntax, but that would require behind-the-scenes manipulation of the script block.
Backward-compatibility considerations
Currently, attempting to use a script block as the replacement operand simply stringifies that block (i.e., uses its string contents as the replacement string).
Since this behavior isn't useful, it's hard to imagine anyone relying on it, so this change probably falls into Bucket 3: Unlikely Grey Area
Environment data
Written as of PowerShell Core v6.0.1