Find and replace at powershell - powershell

My textfile looks like this:
-------------------
Set PRGVER="V1.0.12"
Set PRGDIR=C:\PRGSTD\oif_mes\OIFplus
Set PRGEXE=OIFplus.bat
Set PRGTXT=OIFplus
echo %PRGTXT%, %PRGVER%
start "%PRGTXT%" /D%PRGDIR%\%PRGVER%\ %PRGDIR%\%PRGVER%\%PRGEXE%
----------------------
What I wan't to do, edit this file, only change Set PRGVER="V1.0.12" to a new number, like this Set PRGVER=V1.0.13".
When is start the PS Script, I don't know the whole string, the number between "".
I only know, find string variable: Set PRGVER="".
How can I replace only the first value between ""?

Something like this;
$srt = <your text>
$r = $str -replace "PRGVER=`".*`"", "PRGVER=`"your_replace`""

The following should do it. It finds the a line that starts with 'Set PRGVER="V', followed by any number of digits, then a dot, any number of digits, a dot, any number of digits, and ends with '"'. When found, the line is replaced with 'Set PRGVER="V1.0.13"' and the result is saved back to the file.
(Get-Content file.txt) -replace '^Set PRGVER="V\d+\.\d+.\d+"$','Set PRGVER="V1.0.13"' | Out-File file.txt

Following PoSH will replace PRGVER value:
$newValue = "v123.456.789"
gc D:\temp\text | % { $_ -ireplace '(Set PRGVER=)\"([^"]*)\"', ('$1"' + $newValue + '"') };

You using key: Ctrl + H
More information: https://learn.microsoft.com/en-us/powershell/scripting/windows-powershell/ise/keyboard-shortcuts-for-the-windows-powershell-ise?view=powershell-7

Related

How can I loop through each record of a text file to replace a string of characters

I have a large .txt file containing records where a date string in each record needs to be incremented by 2 days which will then update the field to the right of it which contains dashes --------- with that date. For example, a record contains the following record data:
1440149049845_20191121000000 11/22/2019 -------- 0.000 0.013
I am replacing the -------- dashes with 11/24/2019 (2 days added to the date 11/22/2019) so that it shows as:
1440149049845_20191121000000 11/22/2019 11/24/2019 0.000 0.013
I have the replace working on a single record but need to loop through the entire .txt file to update all of the records. Here is what I tried:
$inputRecords = get-content '\\10.12.7.13\vipsvr\Rancho\MRDF_Report\_Report.txt'
foreach ($line in $inputRecords)
{
$item -match '\d{2}/\d{2}/\d{4}'
$inputRecords -replace '-{2,}',([datetime]$matches.0).adddays(2).tostring('MM/dd/yyyy') -replace '\b0\.000\b','0.412'
}
I get an PS error stating: "Cannot convert null to type "System.DateTime"
I'm sorry but why are we using RegEx for something this simple?
I can see it if there are differently formatted lines in the file, you'd want to make sure you aren't manipulating unintended lines, but that's not indicated in the question. Even still, it doesn't seem like you need to match anything within the line itself. It seems like it's delimited on spaces which would make a simple split a lot easier.
Example:
$File = "C:\temp\Test.txt"
$Output =
ForEach( $Line in Get-Content $File)
{
$TmpArray = $Line.Split(' ')
$TmpArray[2] = (Get-Date $TmpArray[1]).AddDays(2).ToString('M/dd/yyyy')
$TmpArray -join ' '
}
The 3rd element in the array do the calculation and reassign the value...
Notice there's no use of the += operator which is very slow compared to simply assigning the output to a variable. I wouldn't make a thing out of it but considering we don't know how big the file is... Also the String format given before 'mm/dd/yyyy' will result in 00 for the month like for example '00/22/2019', so I changed that to 'M/dd/yyyy'
You can still add logic to skip unnecessary lines if it's needed...
You can send $Output to a file with something like $Output | Out-File <FilePath>
Or this can be converted to a single pipeline that outputs directly to a file using | ForEach{...} instead of ForEach(.. in ..) If the file is truly huge and holding $Output in memory is an issue this is a good alternative.
Let me know if that helps.
You mostly had the right idea, but here are a few suggested changes, but not exactly in this order:
Use a new file instead of trying to replace the old file.
Iterate a line at a time, replace the ------, write to the new file.
Use '-match' instead of '-replace', because as you will see below that you need to manipulate the capture more than a simple '-replace' allows.
Use [datetime]::parseexact instead of trying to just force cast the captured text.
[string[]]$inputRecords = get-content ".\linesource.txt"
[string]$outputRecords
foreach ($line in $inputRecords) {
[string]$newLine = ""
[regex]$logPattern = "^([\d_]+) ([\d/]+) (-+) (.*)$"
if ($line -match $logPattern) {
$origDate = [datetime]::parseexact($Matches[2], 'mm/dd/yyyy', $null)
$replacementDate = $origDate.adddays(2)
$newLine = $Matches[1]
$newLine += " " + $origDate.toString('mm/dd/yyyy')
$newLine += " " + $replacementDate.toString('mm/dd/yyyy')
$newLine += " " + $Matches[4]
} else {
$newLine = $line
}
$outputRecords += "$newLine`n"
}
$outputRecords.ToString()
Even if you don't use the whole solution, hopefully at least parts of it will be helpful to you.
Using the suggested code from adamt8 and Steven, I added to 2 echo statements to show what gets displayed in the variables $logpattern and $line since it is not recognizing the pattern of characters to be updated. This is what displays from the echo:
Options MatchTimeout RightToLeft
CalNOD01 1440151020208_20191205000000 12/06/2019 12/10/2019
None -00:00:00.0010000 False
CalNOD01 1440151020314_20191205000000 12/06/2019 --------
None -00:00:00.0010000 False
this is the rendered output:
CalNOD01 1440151020208_20191205000000 12/06/2019 12/10/2019
CalNOD01 1440151020314_20191205000000 12/06/2019 --------
This is the code that was used:
enter image description here

Remove particular characters from lines and concatenate them

I have a problem where I need to cut specific characters from a line and then concatenate the line with the next lines, separated by commas.
Consider there is a text file abc.txt and I need the last 3 lines from the file. The last 3 lines are in the this format:
11/7/2000 17:22:54 - Hello world.
19/7/2002 8:23:54 - Welcome to the new technology.
24/7/2000 9:00:13 - Eco earth
I need to remove the starting time stamp from each line and then concatenate the lines as
Hello world.,Welcome to the new technology,Eco earth.
The time stamp is not static and I want to make use of a regex
I tried the following:
$Words = (Get-Content -Path .\abc.txt|Select-Object -last 3|Out-String)
$Words = $Words -split('-')
$regex = "[0-9]{1,2}/[0-9]{1,2}/[0-9]{1,4} [0-9]{1,2}:[0-9]{1,2}:[0-9]{1,2}):[0-9]{1,3}"
The output I used to get is like
11/7/2000 17:22:54
Hello world
19/7/2002 8:23:54
Welcome to the new technology.
24/7/2000 9:00:13
Eco earth
There is no need to create a Regex that tries to figure out the timestamp part, because you want to skip that anyway.
This should work:
# read the file and get the last three lines as string array
$txt = Get-Content -Path 'D:\abc.txt' -Tail 3
# loop through the array and change the lines as you go
for ($i = 0; $i -lt $txt.Count; $i++) {
$txt[$i] = ($txt[$i] -split '-', 2)[-1].Trim()
}
# finally, join the array with commas
$txt -join ','
Output:
Hello world.,Welcome to the new technology.,Eco earth
try this:
Get-Content "C:\temp\example.txt" | %{
$array=$_ -split "-", 2
$array[1].Trim()
}
When you have for example : "DATE - blablabla"
If you do .Split("-") on it you get :
Date
blablabla
What you can do is $string.Split("-")[Which_Line] -> so
$string="12/15/18 08:05:10 - Hello World."
$string=$string.Split("-")[1]
Returns : Hello world. (with spaces before)
Now on string you can apply Trim() function - it removes spaces before and after your string
$string=$string.Trim()
Gives you Hello world.
For your answer, if it's static usage (always 3) :
$Words = (Get-Content -Path .\abc.txt|Select-Object -last 3|Out-String).Split("-")
$end=$Words[2].Trim() + "," + $Words[4].Trim() + "," + $Words[6].Trim()

how to remove multiple spaces in multiple file names in a folder in windows 10 using powershell

For example, how can I change multiple file names in a folder: which are in the format " New file " to "New file" in windows 10 using powershell
From https://blogs.technet.microsoft.com/heyscriptingguy/2014/07/18/trim-your-strings-with-powershell/
The easiest Trim method to use is the Trim() method. It is very useful, and it is the method I use most. It easily removes all whitespace characters from the beginning and from the end of a string. This is shown here:
PS C:\> $string = " a String "
PS C:\> $string.Trim()
# => a String
The method is that easy to use. I just call Trim() on any string, and it will clean it up. Unfortunately, the previous output is a bit hard to understand, so let me try a different approach. This time, I obtain the length of the string before I trim it, and I save the resulting string following the trim operation back into a variable. I then obtain the length of the string a second time. Here is the command:
$string = " a String "
$string.Length
# => 10
$string = $string.Trim()
$string
# => a String
$string.Length
# => 8
try this :
Get-ChildItem "C:\Temp" -Recurse -file | Rename-Item -NewName {"{0}{1}" -f $_.BaseName.Trim(), $_.Extension}

Powershell TRIM() is removing extra character

I'm attempting to remove the "\MOSS2013" instance name from my SQL Server instance "WSFCSQLN1\MOSS2013"
This works:
$primaryReplicaGEN = $wsfcsqln2.AvailabilityGroups.PrimaryReplicaServerName
$primaryReplica = $PrimaryReplicaGEN.TRIM("\GEN")
$primaryReplica shows WSFCSQLN1
$primaryReplicaGEN shows WSFCSQLN1\GEN
This does not work:
$primaryReplicaMOSS2013 = $wsfcsqln1MOSS2013.AvailabilityGroups.PrimaryReplicaServerName
$primaryReplica = $PrimaryReplicaMOSS2013.TRIM("\MOSS2013")
$primaryReplica shows WSFCSQLN
$primaryReplicaMOSS2013 shows WSFCSQLN1\MOSS2013
Notice the replica name is missing the 1 at the end even though I did not choose to trim it. Why is it trimming the 1 for this particular string object? How can I force it to trim the correct characters.
Trim() turns the string argument into a [char[]] and removes any of those characters from both ends of the string.
If you just want to grab the server name, use the -split operator and then discard the instance name:
$ServerName = 'WSFCSQLN1\MOSS2013' -split '\\' |Select-Object -First 1
or
$ServerName,$null = 'WSFCSQLN1\MOSS2013' -split '\\'
well, thats how trim works, it will remove all the occurrences of all the characters you are going to trim which it can get to.
"agababga".Trim("ag")
would return bab not ababga, notice it didn't trim a inside bab as it cannot trim b, if you do:
"agababga".Trim("agb")
you would get nothing (empty string) in response
you can use convertfrom-string too like this
$SplitedVar='WSFCSQLN1\MOSS2013' | ConvertFrom-String -Delimiter "\\" -PropertyNames "Domain", "ServerName"
$SplitedVar.Domain
$SplitedVar.ServerName
I'd use a split call:
$primaryReplica = $PrimaryReplicaGEN.split('\')[0];

Remove All Values In A String Before 7th backslash

I have a path inside a txt file that needs to be manipulated, something like:
C:\Jenkins\Automation\Blah\Foo\Bar\646433\Schema\test\473289_12321.ps1
C:\Jenkins\Automation\Blah\Foo\Bar\2112\Schema\QA\473289_123211.ps1
I want to replace everything before the 7th backslash and then replace it with C:\Question. I was doing something similar in Powershell via:
(Get-Content $FullEnvSQLFilePath) | #get the content
Foreach-Object {$_ -replace [Regex]::Escape($StringToReplace), "$StringReplaceValue"} | #look for the string and replace
This worked fine when I knew what the exact verbiage was to look for. We now don't know that but we will want to remove everything before the 7th backslash and replace it with a value. Reverse order works fine too. I wasn't able to have much luck in Powershell via substring doing this. Thanks.
One option:
$text =
'C:\Jenkins\Automation\Blah\Foo\Bar\646433\Schema\test\473289_12321.ps1',
'C:\Jenkins\Automation\Blah\Foo\Bar\2112\Schema\QA\473289_123211.ps1'
$text | foreach {'C:\Question\{0}' -f $_.split('\',8)[-1]}
C:\Question\Schema\test\473289_12321.ps1
C:\Question\Schema\QA\473289_123211.ps1
this ([^\\]*\\){7} regex looks 7 times for a capture group ending on a backslash and replaces it.
UPDATED: .:\\([^\\]*\\){6} regex looks for strings that look like paths starting at any root drive .:\ followed by 6 times a capture group ending on a backslash based on your comment
$text = #"
C:\Jenkins\Automation\Blah\Foo\Bar\646433\Schema\test\473289_12321.ps1
C:\Jenkins\Automation\Blah\Foo\Bar\2112\Schema\QA\473289_123211.ps1
PRINT C:\Jenkins\Automation\Blah\Foo\Baz\2112\Schema\QA\473289_123212.ps1
C:\Jenkins\Automation\Blah\Foo\quux\2112\Schema\QA\473289_123213.ps1
"#
#depending on how you get the text (single string or array)
#$text.Split("`n") | % { $_ -Replace '.:\\([^\\]*\\){6}','C:\Example\' }
$text -Replace ".:\\([^\\`n]*\\){6}","C:\Example\"
Result:
C:\Example\Schema\test\473289_12321.ps1
C:\Example\Schema\QA\473289_123211.ps1
PRINT C:\Example\Schema\QA\473289_123212.ps1
C:\Example\Schema\QA\473289_123213.ps1