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:
Escape a sample of the text you want to replace:
[Regex]::Escape('($17.10)')
==>\(\$17\.10\)
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}\)
Use parentheses to define the amount won as a capture groups:
\((\$\d \.\d{2})\)
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)
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'