Replacing lines with single quote and other special characters in powershell - powershell

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?

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'

Related

add quotation mark to a text file powershell

I need to add the quotation mark to a text file that contains 500 lines text.
The format is inconsistent. It has dashes, dots, numbers, and letters. For example
1527c705-839a-4832-9118-54d4Bd6a0c89
16575getfireshot.com.FireShotCaptureWebpageScreens
3EA2211E.GestetnerDriverUtility
I have tried to code this
$Flist = Get-Content "$home\$user\appfiles\out.txt"
$Flist | %{$_ -replace '^(.*?)', '"'}
I got the result which only added to the beginning of a line.
"Microsoft.WinJS.2.0
The expected result should be
"Microsoft.WinJS.2.0"
How to add quotation-mark to the end of each line as well?
There is no strict need to use a regex (regular expression) in your case (requires PSv4+):
(Get-Content $home\$user\appfiles\out.txt).ForEach({ '"{0}"' -f $_ })
Array method .ForEach() processes each input line via the script block ({ ... }) passed to it.
'"{0}"' -f $_ effectively encloses each input line ($_) in double quotes, via -f, the string-format operator.
If you did want to use a regex:
(Get-Content $home\$user\appfiles\out.txt) -replace '^|$', '"'
Regex ^|$ matches both the start (^) and the end ($) of the input string and replaces both with a " char., effectively enclosing the input string in double quotes.
As for what you tried:
^(.*?)
just matches the very start of the string (^), and nothing else, given that .*? - due to using the non-greedy duplication symbol ? - matches nothing else.
Therefore, replacing what matched with " only placed a " at the start of the input string, not also at the end.
You can use regex to match both:
The beginning of the line ^(.*?)
OR |
The End of the line $
I.e. ^(.*?)|$
$Flist = Get-Content "$home\$user\appfiles\out.txt"
$Flist | %{$_ -replace '^(.*?)|$', '"'}

Powershell replace last two occurrences of a '/' in file path with '.'

I have a filepath, and I'm trying to remove the last two occurrences of the / character into . and also completely remove the '{}' via Powershell to then turn that into a variable.
So, turn this:
xxx-xxx-xx\xxxxxxx\x\{xxxx-xxxxx-xxxx}\xxxxx\xxxxx
Into this:
xxx-xxx-xx\xxxxxxx\x\xxxx-xxxxx-xxxx.xxxxx.xxxxx
I've tried to get this working with the replace cmdlet, but this seems to focus more on replacing all occurrences or the first/last occurrence, which isn't my issue. Any guidance would be appreciated!
Edit:
So, I have an excel file and i'm creating a powershell script that uses a for each loop over every row, which amounts to thousands of entries. For each of those entries, I want to create a secondary variable that will take the full path, and save that path minus the last two slashes. Here's the portion of the script that i'm working on:
Foreach($script in $roboSource)
{
$logFileName = "$($script.a).txt".Replace('(?<=^[^\]+-[^\]+)-','.')
}
$script.a will output thousands of entries in this format:
xxx-xxx-xx\xxxxxxx\x{xxxx-xxxxx-xxxx}\xxxxx\xxxxx
Which is expected.
I want $logFileName to output this:
xxx-xxx-xx\xxxxxxx\x\xxxx-xxxxx-xxxx.xxxxx.xxxxx
I'm just starting to understand regex, and I believe the capture group between the parenthesis should be catching at least one of the '\', but testing attempts show no changes after adding the replace+regex.
Please let me know if I can provide more info.
Thanks!
You can do this in two fairly simply -replace operations:
Remove { and }
Replace the last two \:
$str = 'xxx-xxx-xx\xxxxxxx\x\{xxxx-xxxxx-xxxx}\xxxxx\xxxxx'
$str -replace '[{}]' -replace '\\([^\\]*)\\([^\\]*)$','.$1.$2'
The second pattern matches:
\\ # 1 literal '\'
( # open first capture group
[^\\]* # 0 or more non-'\' characters
) # close first capture group
\\ # 1 literal '\'
( # open second capture group
[^\\]* # 0 or more non-'\' characters
) # close second capture group
$ # end of string
Which we replace with the first and second capture group values, but with . before, instead of \: .$1.$2
If you're using PowerShell Core version 6.1 or newer, you can also take advantage of right-to-left -split:
($str -replace '[{}]' -split '\\',-3) -join '.'
-split '\\',-3 has the same effect as -split '\\',3, but splitting from the right rather than the left.
A 2-step approach is simplest in this case:
# Input string.
$str = 'xxx-xxx-xx\xxxxxxx\x\{xxxx-xxxxx-xxxx}\xxxxx\xxxxx'
# Get everything before the "{"
$prefix = $str -replace '\{.+'
# Get everything starting with the "{", remove "{ and "}",
# and replace "\" with "."
$suffix = $str.Substring($prefix.Length) -replace '[{}]' -replace '\\', '.'
# Output the combined result (or assign to $logFileName)
$prefix + $suffix
If you wanted to do it with a single -replace operation (with nesting), things get more complicated:
Note: This solution requires PowerShell Core (v6.1+)
$str -replace '(.+)\{(.+)\}(.+)',
{ $_.Groups[1].Value + $_.Groups[2].Value + ($_.Groups[3].Value -replace '\\', '.') }
Also see the elegant PS-Core-only -split based solution with a negative index (to split only a fixed number of tokens off the end) in Mathias R. Jessen's helpful answer.
try this
$str='xxx-xxx-xx\xxxxxxx\x\{xxxx-xxxxx-xxxx}\xxxxx\xxxxx'
#remove bracket and split for get array
$Array=$str -replace '[{}]' -split '\\'
#take all element except 2 last elements, and concat after last elems
"{0}.{1}.{2}" -f ($Array[0..($Array.Length -3)] -join '\'), $Array[-2], $Array[-1]

How to select and fill row in form

I've powershell script which should basically fill the empty row in the picture. I'm not able to find solution on how to select that part and fill it with number.
I've tried to find the name with regex but didn't succeed
here is part of the code
$krokPattern = "https://kazdykrokpomaha.ozp.cz/index.php?kroky/index"
$ie.navigate($krokPattern)
while($ie.Busy) { Start-Sleep -Milliseconds 100 }
[regex]$regex = "krok-\d{4}-\d{2}-\d{2}"
$stering = Select-String -Path $krokPattern -Pattern $regex
Image - how it looks like
You can do something like the following with -replace. Just replace the value assigned to $number with whatever value you deem appropriate. However, a proper parser for the language in the file is going to be best.
$regex = [regex]'(?<=type=")[^"]+(?=" name="krok-\d{4}-\d{2}-\d{2}")'
$number = 24
(Get-Content index.html) -replace $regex,$number | Set-Content index.html
Explanation:
Since -replace uses regex matching, we can build off of your current idea. See the following for the $regex breakdown. The goal is to match all characters between the double quotes after type= and before name="krok-####-##-##".
(?<=): Positive Lookbehind
type=": matches the characters type=" literally
[^"]+: matches a single character that is not " one or more times (+).
`(?=): Positive Lookahead
" name="krok-\d{4}-\d{2}-\d{2}": matches literally "krok- followed by 4 digits, a literal -, 2 digits, a literal -, 2 digits, and a final ".
The characters that match $regex are replaced by $number.
See Regex Demo for example and deeper explanation.

How to remove special characters from a text file with PowerShell?

I have a text file and have to remove all weird characters from it. I've already tried the following:
(get-content C:\Users\JuanMa\Desktop\UNB\test.txt) -replace ('.','') | out-file C:\Users\JuanMa\Desktop\UNB\test2.txt
But this leads to an empty output - the file test2.txt remains empty.
This is my text file:
.!..p.ÿÿ.!..! .!. PESCATORE
.!. LEMON SPICE S.R.L.
600 SUR DE MULTIPLAZA ESCAZU
3-102-599284
TEL: 2289-8010 FAX: 2289-5129
INFO#PESCATORECR.COM
.!..! Terminal POS: BARRA
.!.
.! ------------FACTURA-----------
.! .!0 Mesa: B07
.!..! NUMERO : 0068371
.!.Mesa # : B07 Fecha: 25/09/2018
Mesero : CARLOS
Cajero : JOHN Hora : 22:35:06
# Pers : 1 Comandas: 1
Apertura: 22:34 Tiempo/E: 1 Min
.! .!..! .! CANT DESCRIPCION MONTOS
.!.---------------------------------------
1.00 LIMONADA HIERBABUE 2,033.00
.! SubTotal : 2,033.00
%IVA : 264.00
%SER : 203.00
.! .!. TOTALES : 2,501.00
.!..! (COLONES)
En Dolares : 4.55
.!.>> Pago: EFECTIVO> 2,555.00
>> Recibe: 2,555.00
>> Cambio: 54.00
.!
www.gruposinertech.com Vers.15.09A
.!.
AUTORIZADO MEDIANTE RESOLUCION
11-97 DE LA D.G.T.D
.i
.#
Thanks for your help!
Try:
(get-content -Raw C:\Users\JuanMa\Desktop\UNB\test.txt).Replace ('.','') | out-file C:\Users\JuanMa\Desktop\UNB\test2.txt
Get-content return an array by default but if you specify -Raw it will return a string
howdy Juan Manuel Sanchez,
the following will trim the unwanted chars from the beginning of each line in the array of lines you get from Get-Content. it acts on each line in the array without needing to iterate thru the array explicitly.
it's VERY fragile since it hard codes the items. also, it removes all the left hand padding spaces.
$GC_Array -creplace '^[.! pÿ]{1,}' -replace '^0 {2,}'
-creplace is the case-sensitive version of replace
^ means start at the beginning of the line
[] is the character set to replace
char list = dot, exclamation point, space, lowercase p, accented y
{1,} means one or more
the 2nd replace targets start-of-line, a zero digit, & two or more spaces
hope that helps,
lee
The -replace operator uses regular expressions, which use period to denote ANY character, so this strips out anything. If you want to remove literal periods, then prefix the period with a backslash:
(get-content C:\Users\JuanMa\Desktop\UNB\test.txt) -replace ('\.','') | out-file C:\Users\JuanMa\Desktop\UNB\test2.txt
Unfortunately this removes ALL periods, so the periods you may want to keep, e.g. in numbers are lost.
To clean out multiple bad characters, include them in square brackets. This removes 'ÿ','!'
(get-content C:\Users\JuanMa\Desktop\UNB\test.txt) -replace ('[ÿ!]','') | out-file C:\Users\JuanMa\Desktop\UNB\test2.txt
You can chain up these -replace operators to do multiple substitutions:
# Characters ÿ or !
# Replace .! at the start of the line with blank
(get-content C:\Users\JuanMa\Desktop\UNB\test.txt) `
-replace ('[ÿ!]','') `
-replace ('^.!','') |
out-file C:\Users\JuanMa\Desktop\UNB\test2.txt

How can I replace every comma with a space in a text file before a pattern using PowerShell

I have a text file with lines in this format:
FirstName,LastName,SSN,$x.xx,$x.xx,$x.xx
FirstName,MiddleInitial,LastName,SSN,$x.xx,$x.xx,$x.xx
The lines could be in either format. For example:
Joe,Smith,123-45-6789,$150.00,$150.00,$0.00
Jane,F,Doe,987-65-4321,$250.00,$500.00,$0.00
I want to basically turn everything before the SSN into a single field for the name thus:
Joe Smith,123-45-6789,$150.00,$150.00,$0.00
Jane F Doe,987-65-4321,$250.00,$500.00,$0.00
How can I do this using PowerShell? I think I need to use ForEach-Object and at some point replace "," with " ", but I don't know how to specify the pattern. I also don't know how to use a ForEach-Object with a $_.Where so that I can specify the "SkipUntil" mode.
Thanks very much!
Mathias is correct; you want to use the -replace operator, which uses regular expressions. I think this will do what you want:
$string -replace ',(?=.*,\d{3}-\d{2}-\d{4})',' '
The regular expression uses a lookahead (?=) to look for any commas that are followed by any number of any character (. is any character, * is any number of them including 0) that are then followed by a comma immediately followed by a SSN (\d{3}-\d{2}-\d{4}). The concept of "zero-width assertions", such as this lookahead, simply means that it is used to determine the match, but it not actually returned as part of the match.
That's how we're able to match only the commas in the names themselves, and then replace them with a space.
I know it's answered, and neatly so, but I tried to come up with an alternative to using a regex - count the number of commas in a line, then replace either the first one, or the first two, commas in the line.
But strings can't count how many times a character appears in them without using the regex engine(*), and replacements can't be done a specific number of times without using the regex engine(**), so it's not very neat:
$comma = [regex]","
Get-Content data.csv | ForEach {
$numOfCommasToReplace = $comma.Matches($_).Count - 4
$comma.Replace($_, ' ', $numOfCommasToReplace)
} | Out-File data2.csv
Avoiding the regex engine entirely, just for fun, gets me things like this:
Get-Content .\data.csv | ForEach {
$1,$2,$3,$4,$5,$6,$7 = $_ -split ','
if ($7) {"$1 $2 $3,$4,$5,$6,$7"} else {"$1 $2,$3,$4,$5,$6"}
} | Out-File data2.csv
(*) ($line -as [char[]] -eq ',').Count
(**) while ( #counting ) { # split/mangle/join }