Select-String for parsing a Cisco config file - powershell

So I am trying to parse a show tech config file from a cisco router.
The config file is huge so I need to capture everything in between two strings... For Example:
------------------ show running-config ------------------
everything here
------------------ show redundancy history ------------------
I've been able to do it via REGEX:
$TechFile = "filepath"
$Cisco = Get-Content $TechFile
$ShowRunningCfgPattern = "------------------ show running-config ------------------(.*?)------------------ show redundancy history ------------------"
$Results = [regex]::Match($Cisco,$ShowRunningCfgPattern).Groups[1].Value
However this is not an ideal solution as it just clusters everything together making it parsing this information any further impossible
Anyone know a way around this?

You could get the linenumber/index of the particular strings first, then use select-object to only select the lines within those ranges.
See below code example of this, tested on my machine with success:
$startSTR = "------------------ show running-config ------------------"
$endSTR = "------------------ show redundancy history ------------------"
$testfile = "C:\Temp\test.txt"
$content = get-content $testfile
$startIndex = $content.indexof($startSTR) + 1
$endIndex = $content.indexof($endSTR) -1
$desiredContent = $content | select-object -index ($startIndex..$endIndex)
$desiredContent

Related

Powershell - Compare CSV 1 to CSV 2 and then update CSV1

I am not looking for a writing service but please can someone point me in the right direction as I am completely at a lost as to how to proceed.
Overview
I have a CSV which contains a lot of data, some of which comes from a script and some in manually imputed. I can run the script and get new data which is good. What I would like to do is find a way to compare the orginal CSV 1 to the new CSV 2 and update CSV 1.
Code I currently have
$Vips_to_check = #{}
Import-Csv 'C:\Users\user\Documents\20221201\Netscaler VIPs per Cluster_edited - Raw Data.csv' |
Where-Object {$_.PRD -match "No PRD code from VIP IP and VIP has no backend IPs" -or
$_.PRD -match "No PRD code found from VIP or backend IPs" -or
$_.PRD -match "No PRD code found from backend IPs" -and
$_.ipv46 -notcontains "0.0.0.0"} |
$Results_from_PIM = Import-Csv 'C:\Users\user\Documents\20221201\VIP-Owners_edited.csv'
Both of the CSV's have the same headers and layout which is good. I assume!
CSV 1
Name IPV46 Port Curstate Suggested PRD Display Name tech Owner Slack Channel Support Email
name 1 1.2.3.4 8080 Down No No No No No No No
CSV 2
Name IPV46 Port Curstate Suggested PRD Display Name tech Owner Slack Channel Support Email
name 1 1.2.3.4 8080 Down No PRD123 TMOL Gary TMOL Support Support#email.com nsr.sys
I would guess at creating a hashtable but I just can't seem to get my head around the format of them. I tried
$ht = $Results_from_pim #{}
$_.Name = (cant figure out how to reference the cell)
$_.PRD =
$_.("Display Name")
$_.("Tech Owner")
Once I have the data in the hash table how do I overwrite the CSV 1 data?
Any points or guides would be great. I have tried reading up on https://learn.microsoft.com/en-gb/powershell/scripting/learn/deep-dives/everything-about-hashtable?view=powershell-7.3 and https://learn.microsoft.com/en-us/powershell/scripting/learn/deep-dives/everything-about-pscustomobject?view=powershell-7.3
But that left me even more confused.
At the moment the difference is only 4 or 5 entries and it would of been quicker for me to manually edit in excel but as this script gets larger I can see it being more time consuming to do manually.
As always thank you.
UPDATE
$ht = #{}
foreach ($item in $Results_from_PIM) {
"name = $($item.name)"
"prd = $($item.PRD)"
"Display Name = $($item.'Display Name')"
"Tech Owner = $($item.'Tech Owner')"
"Slack Channel = $($item.'Slack Channel')"
"Support Email = $($Item.'Support Email')"
}
I have created the hash table that I wanted from the CSV 2. Just got to get it to compare to CSV 1.
Update 2
Further to #theo request I have adjusted the question. Also to clarify When I want to merge the CSV it is based on matching the Name, IPV46 and Port on both CSV and then moving the updated data from CSV2 into CSV1.
You can do that with the code below (no extra module needed):
$csv1 = 'C:\Users\user\Documents\20221201\Netscaler VIPs per Cluster_edited - Raw Data.csv'
$csv2 = 'C:\Users\user\Documents\20221201\VIP-Owners_edited.csv'
$Results_from_PIM = Import-Csv -Path $csv2
$newData = Import-Csv -Path $csv1 | ForEach-Object {
$search = $_.Name + $_.IPV46 + $_.Port # combine these fields into a single string
$compare = $Results_from_PIM | Where-Object { ($_.Name + $_.IPV46 + $_.Port) -eq $search }
if ($compare) {
# output the result from csv2
$compare
}
else {
# output the original row from csv1
$_
}
}
# now you can save the updated data to a new file or overwrite csv1 if you like
$csv3 = 'C:\Users\user\Documents\20221201\VIP-Owners_Updated.csv'
$newData | Export-Csv -Path $csv3 -NoTypeInformation
P.S. Please read about Formatting
After being direct to In PowerShell, what's the best way to join two tables into one? by #jdweng. I performed the following which seems to have meet my requirements
Install-Module -Name JoinModule -Scope CurrentUser
$Vips_to_check = Import-Csv 'C:\Users\user\Documents\20221201\Netscaler VIPs per Cluster - Raw Data.csv'
$Results_from_PIM = Import-Csv 'C:\Users\user\Documents\20221201\VIP-Owners.csv'
$Vips_to_check | Update-Object $Results_from_PIM -On name, Ipv46, port | Export-Csv 'C:\Users\user\Documents\20221201\Final_data1.csv'
Going to do further testing with larger data sets but appears to work as required.

Logon time script | how to overwrite last logon Powershell

I have a script configured on my GPO that tracks a certain user group their logon times exported to a csv.
Now i've gotten the question, to make it show only the LAST logon time.
At the moment it just writes down every single logon time, but they would like only the last one.
Is there a way to make it overwrite it instead?
Let's say user1 logs in 3 times, i would like to only show it the last one, and that for every user in this group.
The script i have at the moment is a very simple one:
"logon {0} {1} {2:DD-MM-YYYY HH:mm:ss}" -f (Get-Date),$env:username, $env:computername >> \\server\folder\file.csv
Much appreciated if somebody could tell me if it is possible!
First of all, you are appending a line to a text file which is not a CSV file because the values aren't separated by a delimiter character.
Then also, you use the wrong order of values for the -f Format operator: While the template string clearly has the date as the last placeholder in {2:DD-MM-YYYY HH:mm:ss}, you feed that as the first value..
Please also notice that a date format is Case-Sensitive, so you need to change DD-MM-YYYY HH:mm:ss into dd-MM-yyyy HH:mm:ss
I'd advise to change the script you now have to something like:
[PsCustomObject]#{
User = $env:USERNAME
Computer = $env:COMPUTERNAME
LogonDate = '{0:dd-MM-yyyy HH:mm:ss}' -f (Get-Date)
} | Export-Csv -Path '\\server\folder\UserLogon.csv' -NoTypeInformation -Append
Then, when it comes down to reading that file back and preserving only the latest logons, you can do
$data = Import-Csv -Path '\\server\folder\UserLogon.csv' | Group-Object User | ForEach-Object {
$_.Group | Sort-Object {[datetime]::ParseExact($_.LogonDate, 'dd-MM-yyyy HH:mm:ss', $null)} |
Select-Object -Last 1
}
# output on screen
$data
# overwrite the CSV file to keep only the last logons
$data | Export-Csv -Path '\\server\folder\UserLogon.csv' -NoTypeInformation
I think one arrow > should be to overwrite a file.
There is also a command called Out-File with parameters to overwrite a file.
More information on the PowerShell documentation,
https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/out-file?view=powershell-7.1
I must reiterate what others have commented about this not being the best approach to this problem however, given the output file that you have, you could process it like this to get the last record for a given user:
$last = #{} ; Get-Content \\server\folder\file.csv |% { $token = $_ -split ' ' ; $last.$($token[3]) = $_ }
$last
It creates a hash keyed with the username and updates it with the last line from the file. You can also access $last.foo to get the last entry for user foo.
I'd also note that your CSV isn't a CSV which makes it more difficult to process. You'd be better to use Export-CSV or at least putting the commas in. Also, while still not the best approach, you could create a file per user which you could just overwrite each time they login, thus:
new-object PSObject -Property #{ 'date'= (Get-Date); 'username'= $env:username; 'Computer' = $env:computername } | Export-CSV -Path "\\server\folder\$($env:username).csv" -NoTypeInformation
You could import everything for processing by doing:
gci \\server\folder\*.csv |% { import-csv $_ }

Office 365 Powershell - Formatting the output of a foreach-object loop

Good evening all,
Still pretty new to Powershell but I've been trying to get some scripts together to make some of the reporting easier for a lot of the information that we need to pull from our clients' Office 365 tenants.
The script already does what I need it to (grab the subscriptions from the tenant, grab the friendly name of the subscription from my CSV, then write to the console), however my question is about the formatting: I would like to format this output in a table with the column headers Subscriptions, Active, Suspended, Assigned.
$sku = Get-MsolAccountSku | select-object skupartnumber,ActiveUnits,suspendedUnits,ConsumedUnits | sort-object -property skupartnumber
$skudata = import-csv -Header friendlyname,skupartnumber "C:\PShell\SKUs.csv" | where-object {$sku.skupartnumber -eq $_.skupartnumber} | sort-object -property skupartnumber
$skudata | foreach-object {$n = 0}{write-host $skudata.friendlyname[$n], $sku.ActiveUnits[$n], $sku.SuspendedUnits[$n], $sku.ConsumedUnits[$n]; $n = $n + 1}
## Output:
POWER BI (FREE) 1000000 0 1
MICROSOFT TEAMS EXPLORATORY 100 0 6
Here's the script and output, I'm using write-host right now because this formats the data in the same way that we already want it and I can easily copy it out of the console and in to our tickets. When I use write-output, however, it puts each cell on its own line and I can't seem to figure out how to pipe this in to format-table .
$skudata | foreach-object {$n = 0}{write-output $skudata.friendlyname[$n], $sku.ActiveUnits[$n], $sku.SuspendedUnits[$n], $sku.ConsumedUnits[$n]; $n = $n + 1}
# Output:
POWER BI (FREE)
1000000
0
1
MICROSOFT TEAMS EXPLORATORY
100
0
6
I'm already able to get everything I need using the below hash table and simple script, the only problem is that it can't pull the common subscription name and Microsoft's skupartnumber identifier is the best option which isn't always very descriptive. I'm sure there's some very simple solution I'm just missing, but if anyone could point me in the right direction for either solution I've tried it would be greatly appreciated!
$subs = #{Label="Subscription"; Expression={$_.skupartnumber}; Alignment = "right";}
$active = #{Label="Active"; Expression={$_.ActiveUnits}; Alignment = "right"}
$assigned = #{Label="Assigned"; Expression={$_.ConsumedUnits}; Alignment = "right"}
$suspended = #{Label="Suspended"; Expression={$_.SuspendedUnits}; Alignment = "right"}
Get-MsolAccountSku | Format-Table $subs, $active, $suspended, $assigned -autosize
# Output:
Subscription Active Suspended Assigned
------------ ------ --------- --------
POWER_BI_STANDARD 1000000 0 1
TEAMS_EXPLORATORY 100 0 6
PowerShell is an object oriented language and what you need is to gather the info you want in objects for further processing or output.
Try
$result = for ($n = 0; $n -lt $skudata.Count; $n++) {
# output the data as PSObject that gets collected in variable $result
[PsCustomObject]#{
Subscription = $skudata.friendlyname[$n]
Active = $sku.ActiveUnits[$n]
Suspended = $sku.SuspendedUnits[$n]
Assigned = $sku.ConsumedUnits[$n]
}
}
# output on screen
$result | Format-Table -AutoSize
# output to CSV
$result | Export-Csv -Path "C:\PShell\SkuUsage.csv" -NoTypeInformation

Powershell Custom object

This data is store in a file
AUTOM01-AYEHU1:No Updates Available
AUTOM01-AYEHU2:No Updates Available
AUTOM01-AYEHU3:No Updates Available
AUTOM01-AYEHU4:No Updates Available
AUTOM01-AYEHU5:No Updates Available
AUTOM01-AYEHU6:No Updates Available
I have a above dataset in a file i need to create 2 powershell custom object with the name of (SERVERNAME,STATUS) and put respective data into it .
before : is servername and rest is status
This is the answer if you really want 2 objects
$fileLines = #("AUTOM01-AYEHU1:No Updates Available","AUTOM01-AYEHU2:No Updates Available")
$serverArray = [System.Collections.ArrayList]::new()
$statusArray = [System.Collections.ArrayList]::new()
foreach($fileLine in $fileLines)
{
$splittedLine = $fileLine.split(":")
$serverArray.Add([PSCustomObject]#{ServerName=$splittedLine[0]})
$statusArray.add([PsCustomobject]#{Status=$splittedLine[1]})
}
find them in $serverArray and $statusArray
As commented in your previous question, you can simply do
$result = (Get-Content -Path 'thefile.txt' -Raw) -replace ':', '=' | ConvertFrom-StringData
ConvertFrom-StringData returns a Hashtable, in which by default the items are unordered.
As you would like to keep the order as in the input file, you may want to use this instead:
$result = Get-Content -Path 'D:\Test\thefile.txt' | ConvertFrom-String -Delimiter ':' -PropertyNames Server, Status
To return an array of PSCustomObjects:
Server Status
------ ------
AUTOM01-AYEHU1 No Updates Available
AUTOM01-AYEHU2 No Updates Available
AUTOM01-AYEHU3 No Updates Available
AUTOM01-AYEHU4 No Updates Available
AUTOM01-AYEHU5 No Updates Available
AUTOM01-AYEHU6 No Updates Available

powershell compare properties of two network adapters side-by-side

I'm just beginning Powershell, and I want to look at all the properties of two network adapters side-by-side in order to easily see differences.
I've used:
Get-NetAdapter -name "(adapter's name)" | Format-List -Property "*"
multiple times to display all the properties of each adapter one after the other, but it's hard to compare this way.
The perhaps easiest way of doing this is to DIY create a csv file.
I think this will work:
# get the info for the two adapters
$info = Get-NetAdapter -Name 'LAN-connection 1', 'LAN-connection 2'
# create a template string to output csv rows.
# use the systems ListSeparator character so you can double click to open in Excel
$csvline = '"{0}","{1}","{2}"' -replace ',', (Get-Culture).TextInfo.ListSeparator
# create a List object to store the content in
$csvOut = [System.Collections.Generic.List[string]]::new()
# add a headers line
[void]$csvOut.Add(($csvline -f 'Property', $info[0].Name, $info[1].Name))
$info[0].PsObject.Properties | Select-Object * | ForEach-Object {
# get the matching property fro the second adapter
$prop2 = $info[1].PsObject.Properties[$_.Name]
# add the data row
[void]$csvOut.Add(($csvline -f $_.Name, $_.Value, $prop2.Value))
}
# show on screen (although it will probably not fit..)
$csvOut | ConvertFrom-Csv -UseCulture
# write to CSV file to open in Excel
$csvOut | Set-Content -Path 'D:\Test\AdapterInfo.csv'