Replace "special" Strings /---? in PowerShell - powershell

I already know how to replace simple characters or strings in powershell but now I have a headache with a "special" string.
For a normal string/text this line works perfectly fine.
(Get-Content $file.PSPath).Replace('lucky', 'dog') |
Set-Content c:\temp\test.txt
If I want to replace a string which contains a string/text like /---? it doesn't work.
(Get-Content $file.PSPath).Replace('de/---?lucky', 'dog') |
Set-Content c:\temp\test.txt
Also there is no error.

Related

PowerShell, regex, Replace things that are not

Using PowerShell I want to replace everything in a line in the file myFile.txt that is quoted in parenthesis that is not ("Sally") with ("Admin"). Is this the right way to do so, or is there a more appropriate way?
(Get-Content .\myFile.txt) -replace '\(\"(?!Sally).*\"\)', '("Admin")' | Set-Content .\myFile.txt
The contents of myFile.txt is:
("Bob")
("Sally")
("Tom")
And I'd like it to be:
("Admin")
("Sally")
("Admin")

Replacing characters in the middle of a line in a text file with PowerShell

I have the code below that I use to replace a string within a text file and it works. However; I have run into the problem where the string I want to replace is not always exactly the same, but the first few characters are. I want to find the first few characters, count 3 characters ahead, and replace that with what I want.
For example, the line I am replacing may be 123xxx, or 123aaa, etc. but the value I am replacing it with is always going to be known. How would I go about replacing the 123xxx when I won't always know what the xxx is?
((Get-Content -path $ConfPath -Raw) -replace $OldVersion,$NewVersion) | Set-Content -Path $ConfPath
As -replace uses regex, you need to escape the characters that have special meaning like in your case the dot (any character in regex).
$OldVersion = 'jre1\.8\.0_\d{3}' # backslash escape the dots. \d{3} means 3 digits
$NewVersion = 'jre1.8.0_261' # this is just a string to replace with; not regex
((Get-Content -path $ConfPath -Raw) -replace $OldVersion,$NewVersion) | Set-Content -Path $ConfPath
I researched it and figured it out using regex. The code below does exactly what I wanted to do:
((Get-Content -path $ConfPath -Raw) -replace 'jre1.8.0_...',$NewVersion) | Set-Content -Path $ConfPath

Editing a text file inside PowerShell Script

I made a Powershell script to update my mpv scripts. One of them being this
https://raw.githubusercontent.com/mpv-player/mpv/master/player/lua/osc.lua
I want the script to edit and remove all instances of show_message(get_playlist(), 3) from the file.
I tried (get-content .\Scripts\osc.lua) | foreach-object {$_ -replace "show_message(get_playlist(), 3)", ""} | Out-File .\Scripts\osc.lua and (get-content .\portable_config\Scripts\osc.lua) | foreach-object {String.Replace [RegEx]::Escape('show_message(get_playlist(), 3)'),''} | Out-File .\portable_config\Scripts\osc.lua but they dont seem to work.
Basically I want the script to automatically download osc.lua(which works fine as intended) and then remove all instances of show_message(get_playlist(), 3) from the file. My PowerShell version is 5.1.
You can use the following with the Replace Operator:
$regex = [regex]::Escape('show_message(get_playlist(), 3)')
(Get-Content .\Scripts\osc.lua) -replace $regex |
Set-Content .\Scripts\osc.lua
Alternatively, you can use the String.Replace method from the String class, which does not use regex.
(Get-Content .\Scripts\osc.lua).Replace('show_message(get_playlist(), 3)','') |
Set-Content .\Scripts\osc.lua
Explanation:
When using the -replace operator, the matching mechanism is a regex match. Certain characters are metacharacters for regex and must be escaped before they can be interpreted literally. In this case ( and ) need to be escaped. You can either do that manually with \ (\( and \)) or use the Escape() method from the Regex class. From the code above, you can type $regex after its declaration and see how it was escaped.
When replacing a string with an empty string, you do not need to specify a replacement string. 'String' -replace 'ing' has the same results as 'String' -replace 'ing',''
Note: You are mixing Get-Content and Out-File in your code without using the -Encoding parameter. It is possible you could output a different encoding than the original file. If this matters to you, I'd suggest using the -Encoding parameter with the appropriate encoding.

Remove start and end spaces in specific csv column

I am trying to remove start and end spaces in column data in CSV file. I've got a solution to remove all spaces in the csv, but it's creating non-readable text in description column.
Get-Content –path test.csv| ForEach-Object {$_.Trim() -replace "\s+" } | Out-File -filepath out.csv -Encoding ascii
e.g.
'192.168.1.2' ' test-1-TEST' 'Ping Down at least 1 min' '3/11/2017' 'Unix Server' 'Ping' 'critical'
'192.168.1.3' ' test-2-TEST' ' Ping Down at least 3 min' '3/11/2017' 'windows Server' 'Ping' 'critical'
I only want to remove space only from ' test-1-TEST' and not from 'Ping Down at least 1 min'. Is this possible?
"IP","ServerName","Status","Date","ServerType","Test","State"
"192.168.1.2"," test-1-TEST","Ping Down at least 1 min","3/11/2017","Unix Server","Ping","critical"
"192.168.1.3"," test-2-TEST"," Ping Down at least 3 min","3/11/2017","windows Server","Ping","critical"
For example file above:
Import-Csv C:\folder\file.csv | ForEach-Object {
$_.ServerName = $_.ServerName.trim()
$_
} | Export-Csv C:\folder\file2.csv -NoTypeInformation
Replace ServerName with the name of the Column you want to remove spaces from (aka trim).
If your CSV does not have header (which means its not a true CSV) and/or you want to better preserve the original file structure and formatting you could try to expand on your regex a little.
(Get-Content c:\temp\test.txt -Raw) -replace "(?<=')\s+(?=[^' ])|(?<=[^' ])\s+(?=')"
That should remove all leading and trailing spaces inside the quoted values. Not the delimeters themselves.
Read the file in as one string. Could be bad idea depending on file size. Not required as the solution is not dependent on that. Can still be read line be line with the same transformation achieving the same result. Use two replacements that are similar. First is looking for spaces that exist after a single quote but not followed by another quote or space. Second is looking for spaces before a quote that are not preceded by a quote or space.
Just wanted to give a regex example. You can look into this with more detail and explanation at regex101.com. There you will see an alternation pattern instead of two separate replacements.
(Get-Content c:\temp\test.txt -Raw) -replace "(?<=')\s+(?=[^' ])|(?<=[^' ])\s+(?=')"
The first example is a little easier on the eyes.
I was having issues consistently replicating this but if you are having issues with it replacing newlines as well then you can just do the replacement one line at a time and that should work as well.
(Get-Content c:\temp\test.txt) | Foreach-Object{
$_ -replace "(?<=')\s+(?=[^' ])|(?<=[^' ])\s+(?=')"
} | Set-Content c:\temp\test.txt

Basic PowerShell Script Issue: "Expressions are only allowed as the first element of a pipeline"

I'm trying to write a simple script that reads a file, locates a string, replaces the string with another string, and stores all new file contents (with replaced string), in a new file. Here is what I'm using:
(Get-Content C:\file1.txt) | {$_ -replace "this:text", "withthis:text"} | Set-Content C:\file2.txt
The error I'm receiving is: "Expressions are only allowed as the first element of a pipeline"
I'm pretty sure this is because of the colon ":" character being in both the string I'm locating and replacing it with. I've tried escaping the colon character with "\" and "`" characters, but I'm receiving the same errors. Does anyone know what's wrong with this?
Thanks for the help.
The problem is the second element in your pipeline.
{$_ -replace "this:text", "withthis:text"}
This is a scriptblock (i.e. a piece of code). If you want to apply a scriptblock to all of the incoming items on a pipeline you can use the foreach-object cmdlet like this:
(Get-Content C:\file1.txt) | foreach-object {$_ -replace "this:text", "withthis:text"} | Set-Content C:\file2.txt
#shagun is using the % alias for the foreach-object cmdlet, so that code looks correct as well.
I guess it is because after first pipe you are not processing each result. so the right one will be according to me :
(Get-Content C:\file1.txt) | %{$_ -replace "this:text", "withthis:text"} | Set-Content C:\file2.txt