Replace unknown characters in text file using Powershell script? - powershell

I am writing a powershell script to edit multiple text files. All the text files have a line like so
serverUrl=http://localhost:1234
The last 4 numbers vary in each file, but I need to change them all to 9090. I had tried using powershell wildcards like so:
foreach ($file in $files) {
(Get-Content $file).replace('serverUrl=http\://localhost\:????', 'serverUrl=http\://localhost\:9090') | Set-Content $file
}
But these didn't work unfortunately. Is there any way to do this? Thank you

Use the -replace regex operator instead of the String.Replace() method:
(Get-Content $file) -replace 'serverUrl=http://localhost:\d{4}','serverUrl=http://localhost:9080'

Related

Batch command to remove a string pattern from input file

I'm very new to scripting.
I have a couple of files File1.txt and File2.txt. "RemPattern" is the pattern which I'm expecting to find and remove recursively from the above files.
Is it possible to remove them with the help of any windows or powershell batch command?
I have seen Get-Content can be used to remove an entire line of the matched pattern, but it doesn't fit for my case.
(Get-Content 'File1.txt') -notmatch 'RemPattern' | Set-Content 'File1.txt'
Is it required to write a batch file to achieve this or is it possible to do it by batch commands?
You can try out the -replace instead of -nomatch.
(Get-Content 'D:\File.txt') -replace 'RemPattern' | Set-Content 'D:\File.txt'
I was assuming that you wanted to recurse through a set of files and not do them by manually typing the filenames. So you can:
Get-ChildItem F:\ -Filter File*.txt | Foreach-Object{
(Get-Content $_.FullName) | Foreach-Object {$_ -replace 'RemPattern'} | Set-Content $_.FullName
}
The filter here simply checks File*.txt which in your example will do the replacement for both File1.txt and File2.txt without havign to type out each file manually per line. You can change the filter as you please.

Powershell: Editing all Line Feeds and Carriage Returns in a CSV file

Goal is to remove all single "Line Feeds"(LFs) and keep the "Line Feeds" which follow a Carriage Return(CR) in a csv file.
I got a report which includes several LFs in one row, but I only want to keep the "CR+LF" so every row stands for one reported object.
I need a solution in PowerShell, unfortunately I am very new to PowerShell scripting. I tried to alter some scripts on this side for this job, but its not working.
First, I would try to remove all LFs in the file, and then I would replace all remaining CRs with [CR][LF]. But I did not achieve the first step.
$original_file ='C:\Test\Server.csv'
$new_file = 'C:\Test\Server_changed.csv'
(Get-Content $original_file -Raw).Replace('´n',' ') | Set-Content $new_file -Force
(Get-Content $new_file -Raw).Replace('`r','`r`n') | Set-Content $new_file -Force
Source CSV:
"Servername";"CPU","Memory";"Annotation";"OperatingSystem"[CR][LF]
"Server1";"4";"8";"very importand Server!![LF]
If reboot is needed:[LF]
1. Contact Me[LF]
2. Stop all running Services before shutting down the OS[LF]
";"Windows Server 2019";[CR][LF]
How it should look:
"Servername";"CPU","Memory";"Annotation";"OperatingSystem"[CR][LF]
"Server1";"4";"8";"very importand Server!! If reboot is needed: 1. Contact Me 2. Stop all running Services before shutting down the OS ";"Windows Server 2019";[CR][LF]
You can use the -replace operator multiple times to achieve the result.
$original_file ='C:\Test\Server.csv'
$new_file = 'C:\Test\Server_changed.csv'
(Get-Content $original_file -Raw) -replace "(?<!\r)(\n)" -replace "\r(?!\n)","`r`n" |
Set-Content $new_file -NoNewLine -Force
Explanation:
-replace is the regex replace operator as opposed to the string class .Replace(). -replace is used so that we can access the regex mechanisms negative lookahead ((?!)) and negative lookbehind ((?<!)). In each -replace operation, the first set of quotes represent the regex pattern to capture the data you want to replace. The second set of quotes represent the replacement string. If you specify no second set of quotes, then the captured data will just be removed.
-Raw switch is used in Get-Content to prevent PowerShell from reading the file in as an array, which will add newline characters to the data in memory.
-NoNewLine switch on Set-Content is used to not add an additional, trailing newline character at the end of the output file.

INI editing with PowerShell

My problem is I want to change paths in INI Files wich are saved in a folder and its subfolders.
The path of the folder is C:\New\Path\.
Example INI file:
notAIniText = C:\A\Path\notAIniText
maybeAIniText = C:\A\Path\maybeAIniText
AIniText = C:\A\Path\AIniText
I read some other questions about PSini but I don't want to just id because I want to use the script on multiple PC and I don't want to install every time PSIni.
I tried:
$mabyIni = "C:\New\Path"
$AiniFile = Get-ChildItem - Path "C:\New\Path\*" -Include *.ini -Recurse
foreach ($file in $AiniFile) {
Select-String -Path $file -AllMatches "C:\A\Path\" | ForEach-Opject {
$file -replace [regex]:Escape('C:\A\Path'), ('$mabyIni')
} | Set-Content $mabyIni -Include *.ini
But this doesn't work. I tried it with Get-Content too, but that also doesn't work.
Is there any way whitout PSini?
The code in your comment is close, but just has a few syntax issues. It starts out strong:
$mabyIni = "C:\New\Path"
$AiniFile = Get-ChildItem - Path "C:\New\Path*" -include *.ini -recurse
ForEach($file in $AiniFile) {
So far, so good. You define the new path, and you get a list of .ini files in the old path, then you start to loop through those files. This is all good code so far. Then things start to go astray.
I see that you are trying to get the contents of each .ini file, replace the string in question, and then output that file to the new path with this:
(Get-Content $AiniFile.PSPath) | ForEach-Object {
$file -replace [regex]:Escape('C:\A\Path'),('$mabyIni')
}| Set-Content $mabyIni -include *.ini
Unfortunately you're using the wrong variables, and adding in an extra ForEach loop in there as well. Let's start with the Get-Content line. At this point in the script you are looping through files, with each current file being represented by $file. So what you really want to get the contents of is $file, and not $AiniFile.PSPath.
(Get-Content $file)
Ok, that got us the contents of that file as an array of strings. Now, I'm guessing you weren't aware, but the -Replace operator works on arrays of strings. Perfect, we just so happen to have gotten an array of strings! Since the Get-Content command is wrapped in parenthesis it completes first, we can actually just tack on the -Replace command right after it.
(Get-Content $file) -replace [regex]:Escape('C:\A\Path'),$mabyIni
Your -replace command that you had was super close! In fact, I have to give you props for using [regex]::escape() in there. That's totally a pro move, well done! The only issue with it is the replacement string didn't need to be in parenthesis, and it was single quoted, so it would not have expanded the string and your .ini files would have all had a line like:
AIniText = $mabyIni\AIniText
Not exactly what you wanted I'm guessing, so I removed the parenthesis (they weren't hurting anything, but weren't helping either, so for cleanliness and simplicity I got rid of them), and I got rid of the single quotes ' as well since we really just want the string that's stored in that variable.
So now we're looping through files, reading the contents, replacing the old path with the new path, all that's left is to output the new .ini file. It looks like they're already in place, so we just use the existing path for the file, and set the content to the updated data.
(Get-Content $file) -replace [regex]:Escape('C:\A\Path'),$mabyIni | Set-Content -Path $File.FullName
Ok, done! You just have to close the ForEach loop, and run it.
$mabyIni = "C:\New\Path"
$AiniFile = Get-ChildItem - Path "C:\New\Path*" -include *.ini -recurse
ForEach($file in $AiniFile) {
(Get-Content $file) -replace [regex]:Escape('C:\A\Path'),$mabyIni | Set-Content -Path $File.FullName
}

Replace `set` statements to `setx` in a batch script using powershell

Using powershell, I want to take a .bat file and replace all lines in which set is called to set an environment variable and change it to a corresponding setx call. Unfortunately it's not as simple as just doing a search and replace on the file, replacing set for setx, because the syntax is diffferent: set ENVNAME=abc vs setx ENVNAME abc.
Is there a simple way to do this in powershell? To just do the set for setx replacement, I have:
(Get-Content $orig_filename ) | ForEach-Object {$_ -replace "set", "setx"} | Set-Content $new_filename
Any pointers for a powershell novice would be appreciated.
Did some pretty limited testing and I'm not sure what your bat file looks like, but this may work for you.
(Get-Content $orig_filename ) | ForEach-Object {
$_ -replace 'set (.*)\=(.*)','setx $1 $2'
} | Set-Content $new_filename
You could also just chain another -replace to do the work for you. Also made the set > setx replacement a little more less error prone by ensuring you are replacing the word set at the beginning of the string. Since -replace functions as an array operator you do not need the foreach loop.
(Get-Content $orig_filename ) -replace "^set\b", "setx" -replace "="," " | Set-Content $new_filename

Powershell replace special characters string in all files in directory path

I'm trying to create a 'find and replace' script for the website our company just acquired. Right now, I just want to use it to replace their address and phone number with
ours, but I'll likely need to customize it in the future to replace or update other stuffs.
So far, what I got is:
(Get-Content C:\Scripts\Test.txt) |
Foreach-Object {$_ -replace "\*", "#"} |
Set-Content C:\Scripts\Test.txt
which I got from The Scripting Guy :P
However, I need help customizing it. What I need it to do is:
Do it for all files in a directory and all sub-directories, not just one file. The website as far as I can tell is a collection of *.php files
Handle special characters that appear in some addresses, like copyrights (©) pipes (|) commas (,) and periods (.)
Here's the exact string I'm trying to replace (as it appears in the .php's):
<p>©Copyright 2012 GSS | 48009 Fremont Blvd., Fremont, CA 94538 USA</p>
Since this could be the first tool in my powershell toolbox, any explaining of what you're adding or changing would greatly help me understand what's going on.
Bonus points:
Any way to log which files were 'find-and-replace'ed?
My suggestion would be to use a ForEach loop. I don't see the need for a function in this case, just have the code in your ForEach loop. I would define a string to search for, and a string to replace with. When you perform the replace make sure that it is escaped. Something along these lines:
$TxtToFind = "<p>©Copyright 2012 GSS | 48009 Fremont Blvd., Fremont, CA 94538 USA</p>"
$UpdatedTxt = "<p>©Copyright 2014 | 1234 Somenew St., Houston, TX 77045 USA</p>"
$Logfile = "C:\Temp\FileUpdate.log"
ForEach($File in (GCI C:\WebRoot\ -Recurse)){
If($File|Select-String $TxtToFind -SimpleMatch -Quiet){
"Updating lines in $($File.FullName)" |Out-File $Logfile -append
$File|Select-String $TxtToFind -SimpleMatch -AllMatches|Select -ExpandProperty LineNumber -Unique|Out-File $Logfile -append
(GC $File.FullName) | %{$_ -replace [RegEx]::Escape($TxtToFind),$UpdatedTxt} | Set-Content $File.Fullname
}
}
You can leverage regular expression to find/replace the string you desire and the following script will iterate over all the php files within the provided folder recursively.
function ParseFile($file){
#Add logic to parse the file
Write-Host $file.FullName
}
$files = Get-ChildItem -recurse C:\Path -Filter *.php
foreach ($file in $files) {
ParseFile $file
}