I am trying to replace the text ($) with quotation marks in a text file by using PowerShell
Here is the code I am trying, But not giving expected results:
$FilePath = "C:\PT\Test\"
Get-ChildItem $FilePath -Filter *.TXT | ForEach-Object {
(Get-Content $_.FullName) | Foreach-Object {
$_ -replace ',"$"', ',"$",'
} | Set-Content $_.FullName
}
CodePudding user response:
The -replace
operator:
uses a regex as the search-pattern operand, and therefore requires a verbatim
$
to be escaped as\$
in order to be interpreted as such (an unescaped$
is a regex metacharacter representing the end of the input string)also uses
$
as a metacharacter in the substitution operand, namely to refer to the text that the regex captured ($&
) or parts thereof (e.g.$1
to refer to what the first capture group ((...)
) captured). In this case, escape it as$$
.- Note: Situationally, even an unescaped
$
may work, namely if, in combination with the subsequent characters, if any, it cannot be interpreted as a placeholder such as$&
or$1
. However, in the interest of robustness it is better to escape.
- Note: Situationally, even an unescaped
Therefore, use:
PS> ',"$"20' -replace ',"\$"', ',"$$",'
,"$",20
Taking a step back:
As Abraham Zinala suggests, for verbatim string replacements, the .Replace()
string method is sufficient, whose use doesn't necessitate escaping, and which is faster to boot:
PS> ',"$"20'.Replace(',"$"', ',"$",')
,"$",20
Caveat: Unlike -replace
, .Replace()
is case-sensitive - invariably in Windows PowerShell and by default in PowerShell (Core) 7 .
See this answer for a detailed juxtaposition of -replace
and .Replace()
, including how to perform escaping for -replace
programmatically.
To put it all together, along with an optimization that reads each file in full, with Get-Content -Raw
, for much faster processing (to avoid appending a trailing newline, -NoNewLine
is used with Set-Content
):
$FilePath = "C:\PT\Test"
Get-ChildItem $FilePath -Filter *.TXT | ForEach-Object {
(Get-Content -Raw $_.FullName).Replace(',"$"', ',"$",') |
Set-Content -NoNewLine $_.FullName
}
CodePudding user response:
As pointed out by Abraham in his comment, the $
is a reserved character in regex known as Anchor, if you want to match a literal $
using -replace
you would need to escape it: \$
:
Get-ChildItem $FilePath -Filter *.TXT | ForEach-Object {
(Get-Content $_.FullName -Raw) -replace ',"\$"',',"$",' |
Set-Content $_.FullName
}
The other alternative is to use the .Replace(..)
string method which will match literal characters.
Get-ChildItem $FilePath -Filter *.TXT | ForEach-Object {
(Get-Content $_.FullName -Raw).Replace(',"$"',',"$",') |
Set-Content $_.FullName
}
By looking at your code seems like you want to replace ,"$"
with ,"$",
, if this was not the case let me know.