Keep the $character in regular expression replace - regex

Two problems of regular replace
1.need to keep the front $character in the replacement result
2.Skipping the first two lines and the last line is not valid
Code:
$str = #'
#$start1 Random characters
#$start2 Random characters
$p1.AppendBreak($BreakType.LineBreak)
$doc.Protect($ProtectionType.AllowOnlyRevisions, "123")
$footerPara.AppendField("page", $FieldType.FieldPage)
$footerParagraph.AppendField("number of pages", $FieldType.FieldSectionPages)
$txtWatermark.Layout = $WatermarkLayout.Diagonal
$tr1.CharacterFormat.Border.BorderType = $BorderStyle.DashDotStroker
$stri.CharacterFormat.TextBackgroundColor = $Color.LightGray
$document.LoadFromFile(".\Template_HtmlFile.html", $FileFormat.Html, $XHTMLValidationType.None)
$docObject.DocumentObjectType -eq $DocumentObjectType.Picture
$document.Sections[0].Paragraphs[0].InsertSectionBreak($SectionBreakType.NoBreak)
$footerParagraph.Format.HorizontalAlignment = $Spire.Doc.Documents.HorizontalAlignment.Right
#end Random characters
'#
$str | Foreach-Object {
$_ -replace '\$\w+\.(\w+)', '"$1"'
} | Set-Content .\ok.txt
<# -Skip -SkipLast not valid
$str | Foreach-Object {
$_ -replace '\$\w+\.(\w+)', '"$1"'
} | Select-Object -Skip 2 | Select-Object -SkipLast 1 | Set-Content .\ok.txt
#>
Expected results:

At least for your example here string, you need to break it into a string array. Then for the replacement I was only successful when capturing both the beginning and the desired changed text.
$str -split '\r?\n' | Select-Object -Skip 2 |
Select-Object -SkipLast 1 | Foreach-Object {
$_ -replace '(^.+?)\$.+\.(\w+)', '$1"$2"'
} | Set-Content .\ok.txt
Contents of ok.txt
$p1.AppendBreak("LineBreak")
$doc.Protect("AllowOnlyRevisions", "123")
$footerPara.AppendField("page", "FieldPage")
$footerParagraph.AppendField("number of pages", "FieldSectionPages")
$txtWatermark.Layout = "Diagonal"
$tr1.CharacterFormat.Border.BorderType = "DashDotStroker"
$stri.CharacterFormat.TextBackgroundColor = "LightGray"
$document.LoadFromFile(".\Template_HtmlFile.html", "None")
$docObject.DocumentObjectType -eq "Picture"
$document.Sections[0].Paragraphs[0].InsertSectionBreak("NoBreak")
$footerParagraph.Format.HorizontalAlignment = "Right"

Related

PowerShell Regex with csv file

I'm currently trying to match a pattern of IDs and replace with 0 or 1.
example pc0045601234 replace with 1234 the last 4 and add the 3rd digit in front "01234"
I tried the code below but the out only filled the userid column with No matching employee
$reportPath = '.\report.csv'`$reportPath = '.\report.csv'`
$csvPath = '.\output.csv'
$data = Import-Csv -Path $reportPath
$output = #()
foreach ($row in $data) {
$table = "" | Select ID,FirstName,LastName,userid
$table.ID = $row.ID
$table.FirstName = $row.FirstName
$table.LastName = $row.LastName
switch -Wildcard ($row.ID)
{
{$row.ID -match 'P\d\d\d\d\d\D\D\D'} {$table.userid = "Contractor"; continue}
{$row.ID -match 'SEC\d\d\d\D\D\D\D'} {$table.userid = "Contractor"; continue}
{$row.ID.StartsWith("P005700477")} {$table.userid = $row.ID -replace "P005700477","0477"; continue}
{$row.ID.StartsWith("P00570")} {$table.userid = $row.ID -replace "P00570","0"; continue}
default {$table.userid = "No Matching Employee"}
}
$output += $table
}
$output | Export-csv -NoTypeInformation -Path $csvPath
Here are three different ways to achieve the desired result. The first two use the same technique, just written in a different way.
First we put the sample data in a variable as a multiline string array. This is the equivalent as $text = Get-Content $somefile
$text = #'
PC05601234
PC15601234
'# -split [environment]::NewLine
Option 1 # convert to character array, select the 3rd and last 4 digits.
$text | foreach {-join ($_.ToChararray()| select -Skip 2 -First 1 -Last 4)}
Option 2 # same as above, requiring an extra -join to avoid spaces.
$text | foreach {(-join $_.ToChararray()| foreach{$_[2]+(-join $_[-4..-1])})}
Option 3 # my preference, regex. Capture the desired digits and replace the entire string with those two captured values.
$text -replace '^\D+(?!=\d)(\d)\w+([\d]{4}$)','$1$2'
All of these output
01234
11234
Further testing with different char/digit combinations and lengths.
$text = #'
PC05601234
PC15601234
PC0ABC124321
PC1DE4321
PC0A5678
PC1ABCD215678
'# -split [environment]::NewLine
Running the new sample data through each option all produce this output
01234
11234
04321
14321
05678
15678

Parse CSV and decode base64

The goal of this script is supposed to be to find any base64 encoded strings within a particular row of a CSV, grab only the base64, add the correct amount of padding charcters to it, decode it, and write it to an output.
function Get-FileName($initialDirectory) {
[System.Reflection.Assembly]::LoadWithPartialName("System.Sindows.Forms") | Out-Null
$OpenFileDialog = New-Object System.Windows.Forms.OpenFileDialog
$OpenFileDialog.InitialDirectory = $initialDirectory
$OpenFileDialog.Filter = "CSV (*.csv)| *.csv"
$OpenFileDialog.ShowDialog() | Out-Null
$OpenFileDialog.Filename
}
$inputfile = Get-FileName "C:\My Documents\"
$inputdata = Import-Csv $inputfile
$output = "C:\My Documents\output.csv"
$regex = [regex]::New('(?<=-[Ee]ncoded[Cc]ommand\s"??)[\w\d=\/!]{0,792}')
$csv1 = $inputdata | select -ExpandProperty 'NameOfRow' | ? {$_ -ne ""}
| Select-String -Pattern $regex -Allmatches | % {$_.Matches}
| ? {$_.Value -ne ""} | % {$_.Value}
foreach ($line in $csv1) {
$csvL = $line.Length
$csvM = $csvL %= 4
if ($csvM | % {$_ -eq 1}) {
$line | % {$_ + "==="}
} elseif ($csvM | % {$_ -eq 2}) {
$line | % {$_ + "=="}
} elseif ($csvM | % {$_ -eq 3}) {
$line | % {$_ + "="}
}
$decode = [System.Text.Encoding]::ASCII.GetString([System.Convert]::FromBase64String($line))
$decode > $output
}

Powershell: apply multiple queries to a foreach on logs

I need to get the total data transferred value from multiple log files. The data value is shown under the total column in the bytes row.
It is also respectively delimited with a g, m, t or k to show gb/mb/tb/kb.
Total Copied Skipped Mismatch FAILED Extras
Bytes : 54.414 g 54.414 g 0 0 0 0
Currently I have this script which can go through all the files and extract the value between Bytes: and the g but I need to be able to add more queries and to the `foreach file and sum them all to one consistent value.
This is what I have currently but only outputs the kb.
$pattern = "(?<=.*Bytes :.*)\w.+?(?= g.*)"
$pattern1 = "(?<=.*Bytes :.*)\w.+?(?= m.*)"
$pattern2 = "(?<=.*Bytes :.*)\w.+?(?= k.*)"
Get-ChildItem "C:\Users\logs" -Filter "BFR*" | ForEach-Object {
Get-Content "C:\Users\logs\*.log" | where-Object {$_ -match $pattern } | ForEach-Object {
[double] ($matches[0])
} | Measure-Object -Sum | Select-Object -ExpandProperty sum
} | ForEach-Object {
Get-Content "C:\Users\logs\*.log" | where-Object {$_ -match $pattern1 } | ForEach-Object {
[double] ($matches[0])
} | Measure-Object -Sum | Select-Object -ExpandProperty sum
} | ForEach-Object {
Get-Content "C:\Users\logs\*.log" | where-Object {$_ -match $pattern2 } | ForEach-Object {
[double] ($matches[0])
} | Measure-Object -Sum | Select-Object -ExpandProperty sum
}
Here is one possibility. (Sorry #JamesC, it's a 1-liner :-)):
Get-ChildItem .\LogFolder\*.log |
ForEach-Object {$totalBytes = 0}{
Get-Content $_ | Select-String -Pattern "^Bytes\s+:\s+(?<size>\d+\.\d+) (?<units>[tgmk]).*$" |
Foreach-Object {
$size = $_.Matches.Groups[1].Value
switch ($_.Matches.Groups[2].Value)
{
t {$totalbytes += (1tb * $size)}
g {$totalbytes += (1gb * $size)}
m {$totalbytes += (1mb * $size)}
k {$totalbytes += (1kb * $size)}
}
}
} {"Total Bytes: $totalBytes"}

Get the numbers after ":" and count them with the help of powershell

Could someone please help me with extracting and counting the numbers from a text file with PowerShell?
Example: c:\temp\1.txt is some text with semicolon and numbers after them. I need to sum all of these numbers.
blablabl:5 dzfdsfdsfsdfsf:10
sdfsdfsdfdffs:8sdfsfsfdsfdsf:111
5+10+8+111...
What I've tried so far:
$LogText = "C:\temp\1.txt"
[regex]$Regex = "\. (\d+):[1]"
$Matches = $Regex.Matches($LogText)
$Matches | ForEach-Object {
Write-Host $Matches
}
#$array = #()
#$array = new-object collections.arraylist
$array = while ($Matches.Success) {
Write-Host $array[i++]
}
# -------------------------------------------------------------------
$text = Get-Content "C:\temp\1.txt"
[regex]$Regex = "\d"
$Matches = $Regex.Matches($text)
# -------------------------------------------------------------------
$pos = $text.IndexOf(":")
$rightPart = $text.Substring($pos+1)
Write-Host $rightPart
Use Select-String to extract the matches from the file and Measure-Object to do the calculation.
Select-String -Path 'C:\temp\1.txt' -Pattern '(?<=:)\d+' -AllMatches |
Select-Object -Expand Matches |
Select-Object -Expand Value |
Measure-Object -Sum |
Select-Object -Expand Sum
(?<=:) is a positive lookbehind assertion to match the colon preceding the number without making it part of the match.
Try it like that:
$txt=
#"
blablabl:5 dzfdsfdsfsdfsf:10
sdfsdfsdfdffs:8sdfsfsfdsfdsf:111
"#
[regex]$Regex = '\d+'
$sum=0;
$Regex.Matches($txt) | ForEach-Object {
$val = [int]$_.Value
$val
$sum+=$val
}
$sum

Not Match each element of $mylist

I would like to list all uninstall entries and ignore some entries with a whitelist.
Listing the uninstall entries works, but I don't understand how to use $mylist to ignore "app1","app2","app3".
$mylist = #("app1","app2","app3")
Get-ChildItem -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall,
HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall |
Get-ItemProperty |
Where-Object {$_.DisplayName -notmatch $mylist } |
Select-Object -Property DisplayName, UninstallString
Have you an idea?
For checking if a list doesn't contain a particular element use the -notcontains or -notin operator:
... | Where-Object { $mylist -notcontains $_.DisplayName } | ...
or
... | Where-Object { $_.DisplayName -notin $mylist } | ...
Note that the -notin operator isn't available prior to PowerShell v3.
For doing partial matches of one list against another you need something like this:
... | Where-Object {
$name = $_.DisplayName;
-not ($mylist | Where-Object {$name -like "*$_*"})
} | ...
You can construct a regex pattern from the list, and then use the -match operator:
# Construct pattern
$pattern = #($mylist|ForEach-Object {[regex]::Escape($_)}) -join '|'
# Use pattern with -match
... |Where-Object { $_.DisplayName -match $pattern }