I am trying to perform search and replace using RegExs in PowerShell like the following:
Julie found "NoMoney" in "Easter Island" => Julie("Easter Island") = "NoMoney"
John found $SomeMoney$ in "Greenland" => John("Greenland") = $SomeMoney$
Jimmy found $$LotsOfMoney in "Treasure Island" => Jimmy("Treasure Island") = $$LotsOfMoney
Judy found $5 in Tribeca.NY => Judy(Tribeca.NY) = $5
Because the "$" sign has a special meaning in PowerShell REs I am unable to do this successfully for all but the first test where there is no "$". I have tried to escape the $ with backslashes, backticks, and tried combining both as well but no luck.
Can someone help?
I am trying to perform search and replace using RegExs in PowerShell like the following:
Julie found "NoMoney" in "Easter Island" => Julie("Easter Island") = "NoMoney"
John found $SomeMoney$ in "Greenland" => John("Greenland") = $SomeMoney$
Jimmy found $$LotsOfMoney in "Treasure Island" => Jimmy("Treasure Island") = $$LotsOfMoney
Judy found $5 in Tribeca.NY => Judy(Tribeca.NY) = $5
Because the "$" sign has a special meaning in PowerShell REs I am unable to do this successfully for all but the first test where there is no "$". I have tried to escape the $ with backslashes, backticks, and tried combining both as well but no luck.
Can someone help?
Share Improve this question asked Mar 31 at 15:27 hsbatrahsbatra 1512 silver badges10 bronze badges 2 |1 Answer
Reset to default 2Because the "$" sign has a special meaning in PowerShell REs I am unable to do this successfully for all but the first test where there is no "$". I have tried to escape the $ with backslashes, backticks, and tried combining both as well but no luck.
You don't need to match a literal $
to describe the listed strings at all:
$pattern = '^(?<who>\p{Lu}[\w\s]+?) found (?<what>.+?) in (?<where>.+)$'
$testStrings = @(
'Julie found "NoMoney" in "Easter Island"'
'John found $SomeMoney$ in "Greenland"'
'Jimmy found $$LotsOfMoney in "Treasure Island"'
'Judy found $5 in Tribeca.NY'
)
$testStrings |ForEach-Object {
if ($_ -match $pattern) {
"${_} => {0}({1}) = {2}" -f $Matches['who','where','what']
}
}
Outputs:
Julie found "NoMoney" in "Easter Island" => Julie("Easter Island") = "NoMoney" John found $SomeMoney$ in "Greenland" => John("Greenland") = $SomeMoney$ Jimmy found $$LotsOfMoney in "Treasure Island" => Jimmy("Treasure Island") = $$LotsOfMoney Judy found $5 in Tribeca.NY => Judy(Tribeca.NY) = $5
The pattern used above describes:
^ # start of string
(
?<who>
\p{Lu} # 1 upper-case letter
[\w\s]+? # lazily followed by 1 or more word- or whitespace characters
)
found # literal substring " found "
(
?<what>
.+? # lazily followed by at least 1 of any character
)
in # literal substring " in "
(
?<where>
.+ # followed by at least 1 of any character
)
$ # end of string
All the grouping constructs of the form (?<label>pattern)
are named capture groups, allowing us to attach labels to matched/captured substrings.
The $Matches
variable used to store the capture group values is PowerShell-specific, see about_Regular_Expressions
for more information
Although this question appears to arise from an XY problem, for completeness here is the correct escape sequence for a literal $
in a .NET regex pattern:
\$
You can also produce this subpattern programmatically with [regex]::Escape
:
PS ~> [regex]::Escape('$')
\$
$
a problem? – Mathias R. Jessen Commented Mar 31 at 15:30'$' -replace '\$','S'
– js2010 Commented Mar 31 at 16:21