Home > Software design >  Replacing lines with single quote and other special characters in powershell
Replacing lines with single quote and other special characters in powershell

Time:10-11

I'm trying to replace certain lines in several txt documents that might be in subfolders or the current folder. Some of the lines include characters like ' and parenthesis are giving me problems. The lines will repeat multiple times in each file.

This line seems to work

ls *.txt -rec | %{$f=$_; (gc $f.PSPath) | %{$_ -replace " in chips\)", ")"} | sc $f.PSPath}

this one also works

ls *.txt -rec | %{$f=$_; (gc $f.PSPath) | %{$_ -replace [regex]::Escape("won ("), "won "} | sc $f.PSPath}

but this one i cant make it work

ls *.txt -rec | %{$f=$_; (gc $f.PSPath) | %{$_ -replace ":  Hold'em No Limit ($0.50/$1.00 USD)", " - Holdem(No Limit) - $0.50/$1.00"} | sc $f.PSPath}

I have tried with \ before the parenthesis putting the text i want to find with [regex]::Escape() but nothing has worked so far.

What am i missing in order to achieve this?

Bonus problem:

The next problem that i also haven't figured out is that i need to remove both opening and closing parenthesis from a line but has to keep them in other part of the line so for example:

Original line: Seat 5: WTFWY (big blind) won ($17.10)

Wanted output Seat 5: WTFWY (big blind) won $17.10

I was trying to look for "0)" and "won (" and replace them that way, but the "0)" part could be any number and there has to be a more elegant way to do it than to do one for each number with parenthesis. Any ideas for this?

CodePudding user response:

  • As a general rule in PowerShell, only use double-quoteed strings when you need the capabilities of an expansion string.
  • You can use the [Regex]::Escape() method on any string you want to match literally.
  • As an alternative to escaping quotation marks within strings, I find here-strings are easier to read and I don't have to remember how to escape quotes.
  • Replacement text is usually literal, but can reference the groups in the $matches variable created when the regex is matched, using the format $<Group#> in the replacement string. To specify a literal $ as a replacement character, use $$.

So, for your first problem string:

$find = [Regex]::Escape(@'
:  Hold'em No Limit ($0.50/$1.00 USD)
'@)

$replace = ' - Holdem(No Limit) - $$0.50/$$1.00'

@'
Special:  Hold'em No Limit ($0.50/$1.00 USD) - Limited Time
'@ -replace $find , $replace

Output:

PS > $find = [Regex]::Escape(@'
>> :  Hold'em No Limit ($0.50/$1.00 USD)
>> '@)
>>
>> $replace = ' - Holdem(No Limit) - $$0.50/$$1.00'
>>
>> @'
>> Special:  Hold'em No Limit ($0.50/$1.00 USD) - Limited Time
>> '@ -replace $find , $replace
>>
Special - Holdem(No Limit) - $0.50/$1.00 - Limited Time
PS >

For the Bonus question:

  1. Escape a sample of the text you want to replace:

    • [Regex]::Escape('($17.10)') ==> \(\$17\.10\)
  2. Replace literal dollar digis with a match for one or more digits - \d and the decimal digits with a match for exactly two digits - \d{2}:

    • \(\$\d \.\d{2}\)
  3. Use parentheses to define the amount won as a capture groups:

    • \((\$\d \.\d{2})\)
  4. Test the matching:

    PS > 'Seat 5: WTFWY (big blind) won ($17.10)' -match '\((\$\d \.\d{2})\)'
    True
    PS > $matches
    
    Name                           Value
    ----                           -----
    1                              $17.10
    0                              ($17.10)
    
  5. Execute your replace operation:

    PS > 'Seat 5: WTFWY (big blind) won ($17.10)' -replace '\((\$\d \.\d{2})\)' , '$1'
    Seat 5: WTFWY (big blind) won $17.10
    PS >
    


MOre than one way to skin a cat...

Another way to deal with your first string would be to focus only on the text you wish to modify by chaining together two replacement operations. THe first to modify : Hold'em and the second to modify ($0.50/$1.00 USD) as we did in the bonus question:

@'
SPecial :  Hold'em No Limit ($0.50/$1.00 USD) - Limited Time
'@ -replace ":  Hold'em" , ' - Holdem' -replace '\((\$0\.50/\$1\.00) USD\)' , '$1'

Ooutput:

PS > @'
>> SPecial :  Hold'em No Limit ($0.50/$1.00 USD) - Limited Time
>> '@ -replace ":  Hold'em" , ' - Holdem' -replace '\((\$0\.50/\$1\.00) USD\)' , '$1'
SPecial  - Holdem No Limit $0.50/$1.00 - Limited Time
PS >

But actually, ($ at the beginning and USD) at the end are enough to distinguish your targeted substring, and so we can simplify to:

@'
SPecial :  Hold'em No Limit ($0.50/$1.00 USD) - Limited Time
'@ -replace ":  Hold'em" , ' - Holdem' -replace '\((\$. ) USD\)' , '$1'
  • Related