Reputation: 601
I want to create a list of dictionaries, in order for me to export it to CSV. As you may know in PowerShell if you want to export an array filled with strings to CSV file, it won't work, so I have to create objects for this.
But the way I'm doing it if evasive, and I don't feel it's the correct way of creating a list of dictionaries/hashtable, nevertheless I didn't create a function for repeated code (sorry for this).
#add the log file.
$savegrp = Get-Content "J:\savegrp.dec.2015.log"
#filtering into a var just Succeeded/Failed data then replace space with ';' and remove ','
$succeded = ($savegrp -cmatch "Succeeded:") -replace "\s+",";" -replace ",",""
$failed = ($savegrp -cmatch " Failed: ") -replace "\s+",";" -replace ",",""
#creating container where all data will be added
$container = @()
#just a date to save the csv file if this script will be scheduled
$date = Get-Date -format dd.MMMM.yyyy
#take each line of data with 'Succeeded' match and iterate it
for($i=0;$i -le ($succeded.count-1);$i++) {
#split each line by ';' to see how many items are per one line
$s1 = ($succeded[$i]).split(";")
#if in one 'Succeeded' line are just 6 element then is just one server which is ok
if ($s1.count -eq 6){
$PropertyHash = @{}
$PropertyHash = @{
"Date" = $s1[1] + " " + $s1[0]
"Time" = $s1[2]
"Client" = $s1[5]
"Status" = $s1[4].Substring(0,9)
}
$container += New-Object -TypeName PSObject -Property $PropertyHash
}
#if in one 'Succeeded' line are more servers, then stick all sererers to the same info in the line
else{
$count = ($s1.count)
for($a = $count-1;$a -ge 5){
$PropertyHash = @{}
$PropertyHash += @{
"Date" = $s1[1] + " " + $s1[0]
"Time" = $s1[2]
"Client" = $s1[$a]
"Status" = $s1[4].Substring(0,9)
}
$container += New-Object -TypeName PSObject -Property $PropertyHash
$a--
}
}
}
Upvotes: 1
Views: 4419
Reputation: 200373
Something like this should work just fine, provided you have PowerShell v3 or newer:
for ($i = 0; $i -lt $succeded.Count; $i++) {
$date1, $date2, $time, $null, $status, $clients = $succeded[$i].Split(';')
$clients | ForEach-Object {
New-Object -Type PSObject -Property @{
'Date' = "$date2 $date1"
'Time' = $time
'Client' = $_
'Status' = $status.Substring(0,9)
}
} | Export-Csv 'C:\path\to\output.csv' -NoType -Append
}
PowerShell allows you to assign arrays to a list of variables, each of which takes a single element from the array, except for the last one, which takes all the remaining array elements. The statement
$date1, $date2, $time, $null, $status, $clients = $succeded[$i].Split(';')
collects date, time and status in the respective variables $date1
, $date2
, $time
and $status
. The 4th value is discarded by assigning it to $null
. The rest of the array resulting from the split operation (the list of clients) is assigned to the "catch-all" variable $clients
. Then you can pipe that variable into a ForEach-Object
statement where you create one object for each client and append them to your CSV file (note that you need at least PowerShell v3 to be able to append to a CSV).
Edit: If you're stuck with PowerShell v2 or earlier you could also do the export outside the loop. However, for that to work you need to either run it in a subexpression:
(for ($i = 0; $i -lt $succeded.Count; $i++) {
$date1, $date2, $time, $null, $status, $clients = $succeded[$i].Split(';')
$clients | ForEach-Object {
New-Object -Type PSObject -Property @{
'Date' = "$date2 $date1"
'Time' = $time
'Client' = $_
'Status' = $status.Substring(0,9)
}
}
}) | Export-Csv 'C:\path\to\output.csv' -NoType
or collect the results in a variable first:
$container = for ($i = 0; $i -lt $succeded.Count; $i++) {
$date1, $date2, $time, $null, $status, $clients = $succeded[$i].Split(';')
$clients | ForEach-Object {
New-Object -Type PSObject -Property @{
'Date' = "$date2 $date1"
'Time' = $time
'Client' = $_
'Status' = $status.Substring(0,9)
}
}
}
$container | Export-Csv 'C:\path\to\output.csv' -NoType
Upvotes: 3