In der IT gibt es sehr oft den Fall, dass man Daten in einem bestimmten Format bekommt und diese dann in ein anderes Format konvertieren muss. Das neue Format wird benötigt, um die Daten in einem anderen System weiterverarbeiten zu können. Hier kann PowerShell weiterhelfen.
Index
Bei meiner Suche nach Hilfestellungen zum Mapping von Daten aus verschiedenen Systemen bin ich auf das PowerShell Cmdlet ‚Calculated Properties‘ gestoßen.
CSV Dateien als Vorlage
Angenommen man erhält Daten aus einer CSV-Datei des folgenden Formats:
1 2 3 4 5 6 |
id,first_name,last_name,email,city,phone,mobile 1,Muire,Hellyer,mhellyer0@netscape.com,Ganjur,,284-791-8300 2,Rand,Hyndman,rhyndman1@123-reg.co.uk,Nioumamilima,, 3,Isa,Carle,icarle2@kickstarter.com,Sukogunungkrajan,822-549-3376,591-571-6261 4,Raffaello,Digance,rdigance3@sphinn.com,Bromma,,626-743-0389 5,Tatiania,Cromack,tcromack4@ucoz.ru,Gaosheng,963-597-9730,935-581-8254 |
Umbenennung der Eigenschaften
Die Anforderung ist, diese Nutzer auszulesen und in ein anderes Format zu konvertieren, in dem einige ihrer Eigenschaften umbenannt werden (nicht alle). Konkret sollen sich die Properties wie folgt ändern:
- first_name soll zu firstName werden
- last_name soll zu lastName werden
Während man sich nun als PowerShell Neuling den Kopf darüber zerbricht, wie das umzusetzen ist, kommt bereits die nächste Anforderung rein:
Aus „phone“ und „mobile“ soll im Zielobjekt lediglich eine einzige „telephone“ Eigenschaft werden. Darin steht entweder:
- der Wert aus „phone“, sofern nicht leer
- falls „phone“ leer ist: der Wert von „mobile“, sofern nicht leer
- falls beide leer sind, soll „No number provided“ eingetragen werden
Anforderungen im Überblick
Nehmen wir also die obigen Datensätze zur Hand, so gibt es folgende Transformationen:
- aus phone:leer, mobile:284-791-8300 soll telephone:284-791-8300 werden
- aus phone:leer, mobile:leer soll telephone:„No number provided“ werden
- aus phone:822-549-3376, mobile:591-571-6261 soll telephone:822-549-3376 werden
- aus phone:leer, mobile:626-743-0389 soll telephone:626-743-0389 werden
- aus phone:963-597-9730, mobile:935-581-8254 soll telephone:963-597-9730 werden
Wie geht man an diese Aufgabe ran? Man liest das Active Directory Faq!
Ich möchte eine Lösungsmöglichkeit vorstellen, die beide Problemstellungen auf sehr einfache Art löst: Calculated Properties.
Calculated Properties
Calculated Properties sind als HashTable implementiert und kommen oft zusammen mit dem Select-Object Cmdlet. Im folgenden Beispiel selektiere ich nur den ersten Datensatz der CSV-Datei und wandle „first_name“ in „firstName“ um.
1 2 3 |
$users = Import-Csv -Path "mock_data.csv" -Encoding UTF8 $user = $users[0] | Select-Object -Property @{Name="firstName";Expression={$_.first_name}} $user |
Der entscheidende Teil ist dieser:
@{Name=“firstName“;Expression={$_.first_name}}
Mit Name legt man fest, wie die Eigenschaft des Quellobjekts (first_name) im Zielobjekt heißen wird (firstName). Expression kann man einem Scriptblock zuordnen, mit dem man den Inhalt, der zur neuen Eigenschaft gehört, bestimmen bzw. berechnen kann.
Im obigen Fall ist das schon alles. Dem neuen Namen „firstName“ wird der Wert der alten Eigenschaft „first_name“ zugeordnet. In der Ausgabe sieht man nun auch nur den firstName, da nur diese Eigenschaft mit –Property ausgewählt wurde:
Wie schon angedeutet, sind aber auch Berechnungen bzw. Scripts im Expression Block möglich. Das gibt uns, was wir brauchen, um die Telefonnummern zu erzeugen:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
@{Name="telephone";Expression= { $output = "" if(-not([System.String]::IsNullOrWhiteSpace($_.phone))) { $output=$_.phone } elseif(-not([System.String]::IsNullOrWhiteSpace($_.mobile))) { $output=$_.mobile } else { $output="No number provided" } $output }} |
Der Scriptblock der Expression prüft ganz simpel, ob phone einen Wert hat. Sollte ein Wert vorhanden sein, wird dieser standardmäßig genommen, ansonsten wird geprüft, ob mobile einen Wert hat. Falls ja, wird dieser gesetzt. Sollten beide keinen Wert haben, wird „No number provided“ geschrieben.
PS: Nicht vergessen, den gesetzten Wert am Ende auch zurückzugeben.
Das komplette Skript
Der Vollständigkeit halber das ganze Skript:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
$users = Import-Csv -Path "mock_data.csv" -Encoding UTF8 $users | Format-Table $mappedUsers = $users | Select-Object -Property id, ` @{Name="firstName";Expression={$_.first_name}}, ` @{Name="firstName";Expression={$_.last_name}}, ` email, ` city, ` @{Name="telephone";Expression= { $output = "" if(-not([System.String]::IsNullOrWhiteSpace($_.phone))) { $output=$_.phone } elseif(-not([System.String]::IsNullOrWhiteSpace($_.mobile))) { $output=$_.mobile } else { $output="No number provided" } $output }} $mappedUsers | Format-Table |
Nützliche Erklärungen zu Select-Object und -Property
- Select-Object bewirkt, dass die Aktionen auf allen Datensätzen ausgeführt werden und eine neue Liste von Objekten zurückgegeben wird
- -Property gibt an, welche Properties man im Zielobjekt haben will
- Das Zeichen ` ermöglicht es, in PowerShell einen Befehl über mehrere Zeilen zu schreiben.
- Zwischen den Calculated Properties setze ich id, email und city, ohne sie in einen anderen Namen zu konvertieren (braucht man diese Eigenschaften im Zielobjekt nicht, kann man sie einfach weglassen)
Ausgabe der PowerShell – für Tausende User anwendbar
Wie man sieht, ist das Ziel erreicht und was noch schöner ist: Die Lösung skaliert. Es würde für 1.000 oder mehr Nutzer genauso funktionieren. Bei der FirstAttribute hatten wir ein ähnliches Skript bereits für mehrere 10.000 Nutzer im Einsatz. Konkret ging es darum, Daten zwischen einem Readonly Directory und einem AD LDS zu synchronisieren. Letzteres diente als Datenbasis für unser FirstWare IDM-Portal.
Das IDM-Portal bietet Ihnen eine Vielzahl an hilfreichen Funktionalitäten, wie Self Service und Delegation. Damit können Daten direkt von Anwendern oder zuständigen Abteilungen hinzugefügt und aktualisiert werden.
Fazit
Mit Calculated Properties lassen sich auch komplexe Mapping-Operationen für Datensätze in PowerShell umsetzen. Die Syntax ist anfangs zwar etwas gewöhnungsbedürftig, aber man sollte bereit sein, dies für die damit gewonnene Flexibilität in Kauf zu nehmen.
FirstAttribute AG – Ihr Microsoft Consulting Partner
Wir unterstützen Sie bei PowerShell Scripting Fragen.
Nehmen Sie Kontakt zu uns auf.
Leave a Reply
<p>Danke für Ihre Anregungen, Fragen und Hinweise.<br/>Infos zum <a href="https://www.active-directory-faq.dekontakt/">Datenschutz</a></p>