Home > Software engineering >  how to replace text ($) with quotation marks in a text file by using powershell
how to replace text ($) with quotation marks in a text file by using powershell

Time:12-23

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.

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.

  • Related