Home > Software engineering >  powershell -replace: surround captured regex group with dollar signs like: $group$
powershell -replace: surround captured regex group with dollar signs like: $group$

Time:02-03

I want to replace strings like url: `= this.url` with url: $url$

I got quite close with this:

 (Get-Content '.\file') -Replace "``= this.(\w )``", "$ `$1$"

with output url: $ url$. But when I remove extra space then the output breaks. How can I escape/modify "$`$1$" so that it works?

CodePudding user response:

You can use

-Replace "``= this\.(\w )``", '$$$1$$'

Note that

  • The . must be escaped in the regex pattern
  • '$$$1$$' is a $$$1$$ string that contains:
    • $$ - a literal single $ char
    • $1 - the backreference to the first capturing group
    • $$ - a literal single $ char.

CodePudding user response:

To complement Wiktor's effective answer with background information and guidance:

# * Consistent use of '...', obviating the need to `-escape ` and $
# * Verbatim $ chars. in the substitution string escaped as $$
# * Capture-group reference $1 represented as ${1} for visual clarity.
(Get-Content .\file) -replace '`= this\.(\w )`', '$$${1}$$'
  • In the substitution operand of PowerShell's regex-based -replaceoperator, a verbatim $ character must be escaped as $$, given that $-prefixed tokens have special meaning, namely to refer to results of the regex matching operation, such as $1 in your command (a reference to what the 1st, unnamed capture group in the search regex captured).

    • Unlike what the docs partially suggest, such a substitution string is not itself a regex, and any other characters are used verbatim.

    • To programmatically escape $ for verbatim use in a substitution string, it's simplest to use the .Replace() .NET string method, which performs _verbatim (literal) replacements (assuming that all $ instance are to be escaped; e.g. '$foo$'.Replace('$', '$$')

    • Note that, situationally, a capture-group reference such as $1 may need to be disambiguated as ${1}, and you may always choose to do that for visual clarity, as shown above.

  • It is only the search operand is a regex, and there all characters that are regex metacharacters must be \-escaped in order to be used verbatim, which can be done:

    • character-individually, in string literals (amount: \$)
    • programmatically, for entire strings, using
      [regex]::Escape() ([regex]::Escape('amount: $'))
  • To avoid confusion over up-front string interpolation by PowerShell vs. what the .NET regex engine ends up seeing, it's best to consistently use verbatim (single-quoted) strings ('...') rather than expandable (double-quoted) strings ("...").

    • If embedding PowerShell variable values is needed, use techniques such as:
      • string concatenation ('^' [regex]::Escape($foo) '$')

      • or -f, the format operator ('^{0}$' -f [regex]::Escape($foo))

      • In your case, using '...' helps you avoid the `-escaping that "..." requires to make PowerShell treat $ and ` (and ") verbatim, as shown above.

For a comprehensive overview of PowerShell's -replace operator, see this answer.

CodePudding user response:

Powershell 7 version of -replace with a scriptblock 2nd argument. Just assigning $_ into $a to look at it. Note the backquote is a special character inside doublequotes, which I'm avoiding.

'url: `= this.url`' -replace '`= this\.(\w )`', {$a = $_; '$'   $_.groups[1]   '$'}

url: $url$


$a

Groups    : {0, 1}
Success   : True
Name      : 0
Captures  : {0}
Index     : 5
Length    : 12
Value     : `= this.url`
ValueSpan :
  • Related