Inhalt
CSV Dateien zusammenbauen
Wenn Log-Daten in ein CSV geschrieben werden sollen, empfiehlt sich einen Zeitstempel in einem standard Format einzufügen. Die auszugebenden Zeilen können aus einzelnen Datenobjekten zusammengestellt oder zeilenweise manuell als String erstellt werden (die offensichtliche Variante). Bei der objektorientierten Herangehensweise kann eine Zeile sukzessive erweitert werden oder in einem Rutsch gebaut werden. Ebenso kann die CSV Datei gesamthaft geschrieben oder zeilenweise erweitert werden (Append, in früheren PS Versionen nicht vorhanden).
Die Ausschnitte zeigen beide Möglichkeiten.
$datefield = Get-Date -DisplayHint Date -Format yyyy-mm-dd-hh-mm $imdata1 = "1" $imdata2 = "0" $resultsarray =@() $resultline = new-object PSObject $resultline | add-member -membertype NoteProperty -name "Date" -Value $datefield $resultline | add-member -membertype NoteProperty -name "IM_DATA1" -Value $imdata1 $resultline | add-member -membertype NoteProperty -name "IM_DATA2" -Value $imdata2 $resultsarray += $resultline $resultsarray| Export-Csv .\CSV-sample-log.csv -notypeinformation
Alternativ kann man eine Zeile als hashtable von Property Namen und Werten erstellen.
$newrow = New-Object PSObject -Property @{ Date = $datefield IM_DATA1 = $imdata1 IM_DATA2 = $imdata2 } $newrow | Export-Csv .\powershell_2_csv.csv -Append –notypeinformation
Das Resultat:
"Date","IM_DATA1","IM_DATA2" "2014-49-08-07-49","1","0"
Caveat: De Reihenfolge der Werte in der Ausgabe war in meinen Versuchen immer so wie im Code geschriebenen. Dies ist möglicherweise nicht garantiert und man müsste (ab PS 3) einen Cast zu [ordered] or [pscustomobject] machen:
$newrow += [pscustomobject] @{
CSV Dateien speichern
Das grundsätzliche Cmdlet zum Speichern in eine Datei ist Export-CSV. Im Gegensatz dazu gibt das Cmdlet ConvertTo-CSV das Resultat in einen String aus, der dann natürlich in eine Datei geleitet werden kann. ConvertTo-CSV dient aber eher dazu, Objekte und ihre Attribute (keine Methoden) zu Weiterverarbeitung als String bereitzustellen. Als Input wird ein PS Object erwartet, in den Beispielen unten wurde das Array $DataSet.Tables[0] von einer SQL DB Query gefüllt.
Beispiel: als UTF8 schrieben, Datentyp des PS Objects unterdrücken, ; als Trenner (-UseCulture nimmt den aktuellen länderspezifischen Wert)
$DataSet.Tables[0] | Export-CSV -Delimiter ";" $datafilename -encoding UTF8 -NoTypeInformation
Beispiel: mit Leerzeichen als Trenner, selektive Auswahl von Attributen
$DataSet.Tables[0] | Select-Object -Property Day,ReceivedCalls,SuccessfulCalls | Export-CSV $datafilename -Delimiter " " -encoding UTF8 –NoTypeInformation
Beispiel: entfernen von Hochkommata rund um jedem Datenwert
$DataSet.Tables[0] | ConvertTo-Csv -Delimiter ";" -NoTypeInformation | % {$_.Replace('"','')} | Out-File $datafilename
Vor dem Speichern in eine Datei müssen wir möglicherweise einen Fileshare verbinden. Damit man dabei nicht das Passwort im Klartext in das Script schreiben muss, kann man es als Secure String vorgängig abspeichern und bei Bedarf wieder einlesen. Der Secure String verschlüsselt dabei nicht nur das Passwort, sondern auch die SID des verschlüsselnden Users und die SID des Computers, worauf dieses Komnando ausgeführt wird. Somit ist sichergestellt, dass die Datei mit den gespeicherten Passwort auf keiner anderen Machine und von keinem anderen User benutzt werden kann.
Wir können das Passwort von der Konsole interaktiv einlesen und speichern:
read-host -AsSecureString | ConvertFrom-SecureString | Set-Content c:\powershell\pass.txt
oder initial aus einem Klartext-Passwort heraus erzeugen:
$secure_string_pwd = ConvertTo-Securestring "xxxxxx" -asplaintext -force ConvertFrom-SecureString $secure_string_pwd | Set-Content c:\powershell\pass.txt
Bei Gebrauch lesen wir es ein:
$password = Get-Content c:\powershell\pass.txt | ConvertTo-SecureString $credential = New-Object System.Management.Automation.PSCredential "DOMAIN\samaccountname",$password New-PSDrive -Persist -name P -Psprovider FileSystem -root \\server\share -credential $credential
CSV lesen
Das Einlesen einer CSV Datei geht komfortabel: man iteriert über alle Zeilen. Die einzelnen Felder stehen als Properties $_.propertyname zur Verfügung. Import-CSV kennt ähnliche Optionen wie Export-CSV. Praktisch ist, dass bereits beim Einlesen die Header geändert werden können (sodass die Properties anders heissen werden).
Import-Csv -path $inputFile -delimiter ',' | % { try { # read CSV columns und cast to string $myDate = [string]$_.Date $myIM1 = [string]$_.IMDATA1 $myIM2 = [string]$_.IMDATA2 } catch { $logmsg = "*** test catch error: $error[0]" } }
Spalten unformatieren und berechnen
In Powershell ist alles ein Objekt und nicht einfach nur ein String oder ein Array von Buchstaben, wie man es von anderen C-basierten Sprachen her kennt. Als Beispiel für den grossen Komfort, den uns Powershell bietet, hier ein Ausschnitt, wie Resultate aus einer SQL Query über Lync Response Groups weiterverarbeitet werden können. Vor der Ausgabe in eine CSV Datei werden hier neue Spalten eingefügt und deren Werte zeilenweise neu berechnet.
$DataSet.Tables[0].Columns.Add("Day") | Out-Null $DataSet.Tables[0].Columns.Add("ReceivedCalls") | Out-Null $DataSet.Tables[0].Columns.Add("SuccessfulCalls") | Out-Null $DataSet.Tables[0].Columns.Add("OfferedCalls") | Out-Null $DataSet.Tables[0].Columns.Add("AnsweredCalls") | Out-Null $DataSet.Tables[0].Columns.Add("TransferredCalls") | Out-Null ($DataSet.Tables[0]) | foreach { $_.ReceivedCalls = $_.SOCCnt + $_.FOCCnt $_.SuccessfulCalls = $_.SOCCnt + 0 $_.OfferedCalls = $_.SACCnt + $_.FACCnt $_.AnsweredCalls = $_.SLCnt + 0 if (-not $_.AnsweredCalls ) { $_.AnsweredCalls = "9999"} $_.TransferredCalls = $_.STCCnt + $_.FTCCnt # shorten date (samples column) $_.Day = ([datetime]$_.Sample).tostring('dd.MM.yyyy') }
Die Ausgabe mit Filter haben wir schon angetroffen. Hier werden die neuen Spalten exportiert und die Spalten mit den nicht benutzten Rohdaten unterdrückt.
$DataSet.Tables[0] | Select-Object -Property Day,ReceivedCalls,SuccessfulCalls | Export-CSV $datafilename -Delimiter " " -encoding UTF8 –NoTypeInformation