Reputation: 1192
This is driving me nuts! Would appreciate any pointers as to what is going on, please!
$alpha = 'aaa.bbb.$connection.ccc.ddd'
$s = [regex]::match($alpha,"\$.+?(?=\.)").Value
"Alpha is: $alpha"
"Matched chunk is: $s"
$newChunk = "'" + $s + "'"
"New chunk is: $newChunk"
$beta = $alpha -replace $s,$newChunk
"Beta is: $beta"
This produces the following output:
Alpha is: aaa.bbb.$connection.ccc.ddd
Matched chunk is: $connection
New chunk is: '$connection'
Beta is: aaa.bbb.$connection.ccc.ddd
I am trying to identify/match character sequences in a path that begin with the literal '$' and continue until, but does not include a literal dot "." char. In the example code above the string would be "$connection".
Then I need to wrap that string in single quotes, so in the example above the $newChunk value would become '$connection' including the single quotes.
Next, I need to replace the matched value with the new single quoted value in the original string. No matter what I try (same with [regex]::match method too), the single quotes are stripped out. So, effectively, I am trying to turn:
aaa.bbb.$connection.ccc.ddd
into
aaa.bbb.'$connection'.ccc.ddd
Using Powershell 7.1 and would really appreciate someone telling me why this does not work. Thanks!
Upvotes: 2
Views: 187
Reputation: 437638
Ryszard Czech's helpful answer is definitely the best solution: generically referring to what the regex-based -replace
operator matched, in its replacement operand, with placeholder $&
is the simplest and most robust solution.
See this answer for other placeholders you can use, such as what preceded ($`
) or succeeded ($'
) the match, or what a capture group matched (e.g. $1
).
As for what you tried:
Instead of using your regex \$.+?(?=\.)
directly with the regex-based -replace
operator, you used the verbatim result of an explicit [regex].Match()
call as the search operand (first RHS operand) for -replace
, which is then again interpreted as a regex.
-replace
search operand, any regex metacharacters - i.e., characters with special syntactic meaning - must be \
-escaped, such as the verbatim $
in your string, which you can do with [regex]::Escape($s)
Additionally, you used a replacement operand that had an embedded $
char. that you meant to be interpreted verbatim, but $
in the replacement operand is a metacharacter, referring to placeholders such as $&
.
In order to use a string verbatim as the -replace
replacement operand, you must programmatically escape embedded $
chars. as $$
[1]:
The simplest approach is to use the [string]
type's literal-substring replacement method, .Replace()
:
$replacementOperand = '$foo'
'value is: (value)' -replace '\(value\)', $replacementOperand.Replace('$', '$$')
Thus, your original approach would have had to use the following command - but do note that Ryszard's solution is much simpler overall:
$beta = $alpha -replace [regex]::replace($s), $newChunk.Replace('$', '$$')
[1] Situationally you may get away without escaping, because a $
-prefixed token that isn't recognized as a placeholder is left untouched (e.g., 'bar' -replace 'r', '$x'
behaves the same as 'bar' -replace 'r', '$$x'
), but the only robust solution is to escape verbatim $
chars. by doubling them.
Upvotes: 1
Reputation: 18611
Use
$beta = $alpha -replace '\$[^.]+', "'$&'"
See proof.
Explanation
--------------------------------------------------------------------------------
\$ '$'
--------------------------------------------------------------------------------
[^.]+ any character except: '.' (1 or more times
(matching the most amount possible))
The $&
is the placeholder for the entire match.
Upvotes: 3