PowerShell -replace operator exhibits quirky behavior with particular data

powershellreplace

The presence of the special PowerShell variable $_ in the replacement string causes odd behavior; I am wondering if there is something about escaping I am missing or if this is just a defect.

The output of this code…

$text = "WORD1 WORD2 WORD3 WORD4"
$newText = 'new $_ text'
$newText
$text -replace "WORD3",$newText

… is this, where $_ is interpolated with the original contents of $text for some reason during the replace operation:

new $_ text
WORD1 WORD2 new WORD1 WORD2 WORD3 WORD4 text WORD4

Replace should treat its second parameter as a literal–using no interpolation–which is true for most anything, including things that look like regular variables like this:

$foo = "HELLO"
$text = "WORD1 WORD2 WORD3 WORD4"
$newText = 'new $foo text'
$newText
$text -replace "WORD3",$newText

… and its output is:

new $foo text
WORD1 WORD2 new $foo text WORD4

But the presence of $_ causes interpolation. Similar problem with $$. As far as I can tell no other special variables cause interpolation.

Note that the same problem occurs with inline code like this:

$text -replace "WORD3",'new $_ text'

I split it out above just to show that the replacement string was correct before the replace operation. Curiously, if I replace the single quotes with double quotes here to ask for interpolation, the result is different. That is, this code:

$text -replace "WORD3","new $_ text"

produces the expected

WORD1 WORD2 new  text WORD4

not the baffling

WORD1 WORD2 new $foo text WORD4

Best Answer

I was able to do what you want using

$text.replace('WORD3','new $_ text')

this gives the expected output

WORD1 WORD2 new $_ text WORD4