Update script using Regex commands - regex

Created the following PS script to pull data from some reports and dump extracted data into a .csv file:
$csvContents = #()
$hashTable = #{}
$count = 0
Get-ChildItem $PSRoot\NU_*.txt | %{
Get-Content $_ |
?{$_ -imatch 'Percent of memory in use' -or $_ -imatch 'Remaining Space' -or $_ -imatch 'Percent of CPU in use' -or $_ -imatch 'Node Number' `
-or $_ -imatch 'Generated' -or $_ -imatch 'Client Name' -or $_ -imatch 'Windows Ver:' -or $_ -imatch 'ActiveName' -or $_ -imatch 'node \d+'} | %{
If($_ -imatch 'ActiveName'){
$name = (([regex]::Matches($_,'\w+') | select value).value )
$store = ([regex]::Matches($name[2],'\b\d+') | select value).value
}
If($_ -imatch 'Node Number'){
$NodeNumber = ([regex]::Matches($_,'\b\d+') | select value).value
}
If($_ -imatch 'memory in use'){
$memory = ([regex]::Matches($_,'\b\d+') | select value).value
}
If($_ -imatch 'Remaining Space'){
$space = ([regex]::Matches($_,'\b\d+') | select value).value
}
If($_ -imatch 'CPU in use'){
$cpu = ([regex]::Matches($_,'\b\d+') | select value).value
}
If($_ -imatch 'Generated'){
$Date = ([regex]::Matches($_,'(\d+)-(\d+)-(\d+) (\d+):(\d+):(?:\d+)') | select value).value #[0..2] -join '-'
}
If($_ -imatch 'Client Name'){
$ClientName = (([regex]::Matches($_,'\s+(\s+\w+)') | select value).value -join ',').trim()
}
If($_ -imatch 'Windows Ver:'){
$WinVer = ([regex]::Matches($_,'Windows Ver: (\d+)\.(\d+)') | select value).value -join ','
}
$obj = [PSCustomObject]#{
STORE = $store
DATE = $Date
NODENUMBER = $NodeNumber
POSTYPE = $ClientName
MEMORYUSAGE = $memory
FREEHDSPACE = $space
CPUUSAGE = $cpu
WINDOWSVERSION = $WinVer
}
If($_ -imatch 'Node \d+'){
$hashTable.Add($count,$obj)
$count++
}
}
}
$hashTable.values.GetEnumerator() | Sort-Object -Property DATE | ConvertTo-Csv -NoTypeInformation | Set-Content -path "$Reports\$($Store)_$(Get-Date -f yyyy-MM-dd)_$((Get-Date).tostring("hh-mm-ss")).csv" -force
Example of .csv file:
In the POSTYPE column the PCSERVER is showing 0 and I would like it to show 123. The EPC4 is showing 0 and I would like it to show 155. Any suggestions on how I can do this.

If you want to overwrite your source data and always use the numbers you mention, you can just add another couple of If statements before creating your $obj:
If($ClientName -eq 'PCSERVER'){
$NodeNumber = 123
}
If($ClientName -eq 'EPC4'){
$NodeNumber = 155
}

Related

Filter list from multiple values

I have this line:
$output.GetEnumerator() | Where-Object { $_.ItemPath -notlike "*.zip" } | Select ItemPath
Example output:
ItemPath
--------
\\devws04
\\devws04\c$
\\devws04\c$\share
\\devws04\c$\share\Dieser ORdner ist offline erstellt worden
\\devws04\c$\share\FileOfflineMode - Copy.txt
\\devws04\c$\share\FileOfflineMode.txt
\\devws04\c$\share\Personal
\\devws04\c$\share\Personal\Okey Cuuus.txt
\\devws04\c$\share\Portfolio.txt
The line excludes path values which contain "*.zip". It works but I want to use a variable at this place and not append everything to the same line with "and".
I tried following:
$ignoreFiles = #("*.zip", "*.psd")
$output.GetEnumerator() | Where-Object { $_.ItemPath -notin $ignoreFiles } | Select ItemPath
And several other snippets but none of them worked. It did just nothing to the result. Any hint appreciated!
This is the full output:
ItemPath
--------
\\devws04
\\devws04\c$
\\devws04\c$\share
\\devws04\c$\share\Dieser ORdner ist offline erstellt worden
\\devws04\c$\share\Dieser ORdner ist offline erstellt worden\MeineofflineDateien.zip
\\devws04\c$\share\FileOfflineMode - Copy.txt
\\devws04\c$\share\FileOfflineMode.txt
\\devws04\c$\share\Personal
\\devws04\c$\share\Personal\Okey Cuuus.txt
\\devws04\c$\share\Portfolio.txt
EDIT:
This is the actual code and my goal is to do a csv-export but before I want to filter the values like described above:
$ignoreFiles = "\.zip|\.psd"
#$ignoreFiles = #("*.zip", "*.psd")
$query = Get-WmiObject -query "SELECT * FROM Win32_OfflineFilesItem"
$hostName = [System.Net.Dns]::GetHostName()
$user = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name
$output = #()
$query | ? {
$output += [PSCustomObject] #{
User = $user
Hostname = $hostName
ItemPath = $_.ItemPath
}
}
$output | Export-CSV $outputPath -NoTypeInformation # ONLY EXPORT OBJECTS WHERE $_.ItemPath does not contain one of the values from $ignoreFiles!
You could also use regex to help you with the challenge that you face:
$regex = "\.zip|\.psd"
$paths = $output.GetEnumerator() | Select-Object ItemPath
$paths.ItemPath -notmatch $regex
Updated with extra answer
I would say this should do the trick
$output = $output | Where-Object {$_.ItemPath -notmatch $ignoreFiles }
$output | Export-CSV $outputPath -NoTypeInformation # ONLY EXPORT OBJECTS WHERE $_.ItemPath does not contain one of the values from $ignoreFiles!
not sure what $output is,
But using a variable should work exactly the same:
$ext = "*.zip"
$output | Where-Object { $_.ItemPath -notlike $ext } | Select ItemPath
You could also use -notin for an array of things, depending on the input:
gci | Where-Object { $_.Extension -notin ($ext, ".7z") } | Select FullName

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
}

How to stream text with powershell and regex match on multiline

I have a text file that an application constantly errors to. I want to monitor this file with Powershell and log every error to another source.
Problem to solve: how do i pass multiline text when we are in -wait? Get-Content is passing arrays of strings.
$File = 'C:\Windows\Temp\test.txt'
$content = Get-Content -Path $file
# get stream of text
Get-Content $file -wait -Tail 0 | ForEach-Object {
if ($_ -match '(<ACVS_T>)((.|\n)*)(<\/ACVS_T>)+'){
write-host 'match found!'
}
}
Example of text junks that get drop:
<ACVS_T>
<ACVS_D>03/01/2017 17:24:03.602</ACVS_D>
<ACVS_TI>bf37ba1c9,iSTAR Server Compone</ACVS_TI>
<ACVS_C>ClusterPort</ACVS_C>
<ACVS_S>SoftwareHouse.NextGen.HardwareInterface.Nantucket.Framework.ClusterPort.HandleErrorState( )
</ACVS_S>
<ACVS_M>
ERROR MESSAGE FROM APP
</ACVS_M>
<ACVS_ST>
</ACVS_ST>
</ACVS_T>
solved it!
$File = 'D:\Program Files (x86)\Tyco\CrossFire\Logging\SystemTrace.Log'
$content = Get-Content -Path $file
# get stream of text
$text = ''
Get-Content $file -wait -Tail 0 | ForEach-Object {
$text +=$_
if ($text -match '(<ACVS_T>)((.|\n)*)(<\/ACVS_T>)+'){
[xml]$XML = "<Root>" + $text + "</Root>"
$text='' #clear it for next one
$XML.Root.ACVS_T | ForEach-Object {
$Obj = '' | Select-Object -Property ACVS_D, ACVS_TI, ACVS_C, ACVS_S, ACVS_M, ACVS_ST
$Obj.ACVS_D = $_.ACVS_D
$Obj.ACVS_ST = $_.ACVS_ST
$Obj.ACVS_C = $_.ACVS_C
$Obj.ACVS_S = $_.ACVS_S
$Obj.ACVS_M = $_.ACVS_M
$Obj.ACVS_ST = $_.ACVS_ST
write-host "`n`n$($Obj.ACVS_M)"
}
}
}

How to regex multiple times powershell

I am just learning powershell and cant find how to run differents regex with powershell.
$input_path = 'C:\site-download\input.txt'
$output_file = 'C:\site-download\output.txt'
$regex = '(?<month>VPIP<\/span><span class=""right"">\d{2}.\d{1})'
$regex2 = '(?<month>VPIP<\/span><span class=""right"">\d{2}.\d{1})'
$regex3 = '(?<month>VPIP<\/span><span class=""right"">\d{2}.\d{1})'
$regex... = '(?<month>VPIP<\/span><span class=""right"">\d{2}.\d{1})'
select-string -Path $input_path -Pattern $regex -AllMatches | % { $_.Matches} | % { $_.Value }|
Foreach-Object {$_ -replace '</span><span class=""right"">', ' = '} > $output_file
$regex
works good, but how can i add $regex2 and $regex3 ... to outputfile?
Thanks
You just need a small change to your last section of your pipeline. Instead of using > $output_file just pipe the output of the foreach loop to Out-File cmdlet. So you should be able to have your last line of code look like this:
select-string -Path $input_path -Pattern $regex -AllMatches |
% { $_.Matches} | % { $_.Value } |
Foreach-Object {$_ -replace '</span><span class=""right"">', ' = '} |
Out-File $output_file

Powershell search matching string in word document

I have a simple requirement. I need to search a string in Word document and as result I need to get matching line / some words around in document.
So far, I could successfully search a string in folder containing Word documents but it returns True / False based on whether it could find search string or not.
#ERROR REPORTING ALL
Set-StrictMode -Version latest
$path = "c:\MORLAB"
$files = Get-Childitem $path -Include *.docx,*.doc -Recurse | Where-Object { !($_.psiscontainer) }
$output = "c:\wordfiletry.txt"
$application = New-Object -comobject word.application
$application.visible = $False
$findtext = "CRHPCD01"
Function getStringMatch
{
# Loop through all *.doc files in the $path directory
Foreach ($file In $files)
{
$document = $application.documents.open($file.FullName,$false,$true)
$range = $document.content
$wordFound = $range.find.execute($findText)
if($wordFound)
{
"$file.fullname has $wordfound" | Out-File $output -Append
}
}
$document.close()
$application.quit()
}
getStringMatch
#ERROR REPORTING ALL
Set-StrictMode -Version latest
$path = "c:\Temp"
$files = Get-Childitem $path -Include *.docx,*.doc -Recurse | Where-Object { !($_.psiscontainer) }
$output = "c:\temp\wordfiletry.csv"
$application = New-Object -comobject word.application
$application.visible = $False
$findtext = "First"
$charactersAround = 30
$results = #{}
Function getStringMatch
{
# Loop through all *.doc files in the $path directory
Foreach ($file In $files)
{
$document = $application.documents.open($file.FullName,$false,$true)
$range = $document.content
If($range.Text -match ".{$($charactersAround)}$($findtext).{$($charactersAround)}"){
$properties = #{
File = $file.FullName
Match = $findtext
TextAround = $Matches[0]
}
$results += New-Object -TypeName PsCustomObject -Property $properties
}
}
If($results){
$results | Export-Csv $output -NoTypeInformation
}
$document.close()
$application.quit()
}
getStringMatch
import-csv $output
There are a couple of ways to get what you want. A simple approach is since you have the text of the document already lets perform a regex match on it and return the results and more. This helps in trying to address getting some words around in document.
We have the variable $charactersAround which sets the number of characters to match around the $findtext. Also I though the output was a better fit for a CSV file so I used $results to capture a hashtable of properties that, in the end, are output to a csv file.
Be sure to change the variables for your own testing. Now that we are using regex to locate the matches this opens up a world of possibilities.
Sample Output
Match TextAround File
----- ---------- ----
First dley Air Services Limited dba First Air meets or exceeds all term C:\Temp\20120315132117214.docx
Thanks! You provided a great solution to use PowerShell regex expressions to look for information in a Word document. I needed to modify it to meet my needs. Maybe, it will help someone else. It reads each line of the word document, and then uses the regex expression to determine if the line is a match. The output could easily be modified or dumped to a log file.
Set-StrictMode -Version latest
$path = "c:\Temp\pii"
$files = Get-Childitem $path -Include *.docx,*.doc -Recurse | Where-Object { !($_.psiscontainer) }
$application = New-Object -comobject word.application
$application.visible = $False
$findtext = "[0-9]" #regex
Function getStringMatch
{
# Loop through all *.doc files in the $path directory
Foreach ($file In $files) {
$document = $application.documents.open($file.FullName,$false,$true)
$arrContents = $document.content.text.split()
$varCounter = 0
ForEach ($line in $arrContents) {
$varCounter++
If($line -match $findtext) {
"File: $file Found: $line Line: $varCounter"
}
}
$document.close()
}
$application.quit()
}
getStringMatch
Good answer from #Matt.
I improved it a little (new PowerShell version have problems with the given array. And to search big amount of documents it runs out of memory.
Here is my improved version:
#ERROR REPORTING ALL
Set-StrictMode -Version latest
$path = "c:\Temp"
$files = Get-Childitem $path -Include *.docx,*.doc -Recurse | Where-Object { !($_.psiscontainer) }
$output = "c:\temp\wordfiletry.csv"
$application = New-Object -comobject word.application
$application.visible = $False
$findtext = "First"
$charactersAround = 30
$results = #{}
Function getStringMatch
{
# Loop through all *.doc files in the $path directory
Foreach ($file In $files)
{
$document = $application.documents.open($file.FullName,$false,$true)
$range = $document.content
If($range.Text -match ".{$($charactersAround)}$($findtext).{$($charactersAround)}"){
$properties = #{
File = $file.FullName
Match = $findtext
TextAround = $Matches[0]
}
$results += #(New-Object -TypeName PsCustomObject -Property $properties)
}
$document.close()
}
If($results){
$results | Export-Csv $output -NoTypeInformation
}
$application.quit()
}
getStringMatch
import-csv $output
Use the function like this:
PS> WordGrep -File ./Myfile.docx -Grep one, two, three
function WordGrep{
param(
[string]$File,
[string[]]$Grep,
[switch]$WordMode,
[switch]$EscapeMode
)
$WordApp = New-Object -comobject word.application
$WordApp.visible = $False
try {
$document = $WordApp.documents.open($File, $false, $true)
$arrContents = $document.content.text.split()
$found = $false
foreach ($line in $arrContents) {
foreach ($pattern in $Grep) {
if ($EscapeMode) {
$pattern = [Regex]::Escape($pattern)
}
if ($WordMode) {
$pattern = "\b${pattern}\b"
}
if ($line -imatch $pattern) {
write-host -ForegroundColor Cyan -NoNewLine "$file`:"
write-host " $line"
break;
}
}
}
$document.close()
}
finally {
$WordApp.quit()
}
}