Tags: PowerShell
SQL kann bekanntlich mit dem Befehl GROUP BY das Ergebnis einer Abfrage nach den Werten in einer oder mehreren Spalten gruppieren. Aber auch PowerShell ist dazu in der Lage, wenn man an Group-Object tabellarische Daten übergibt, wie sie von vielen Cmdlets erzeugt werden.
Zu den wichtigsten Operationen bei der Bearbeitung von Daten gehören das Filtern, Sortieren und eben auch das Gruppieren. Häufig ist es notwendig, diese Maßnahmen zu kombinieren, um ans gewünschte Ziel zu kommen.
Dateinamen anhand der Erweiterung gruppieren
So könnte man etwa eine Liste mit Dateinamen, wie sie Get-ChildItem ausgibt, erst nach Extension sortieren und dann nach dieser Eigenschaft gruppieren. Dies hätte den Vorteil, dass Group-Object die Liste aller gefundenen Erweiterungen und die Häufigkeit ihres Vorkommens nicht in beliebiger, sondern in alphabetischer Reihenfolge anzeigt. Filter ließen sich etwa nutzen, um alle Datensätze auszuschließen, die nur einmal vorkommen.
Um beim ersten Beispiel zu bleiben, ließe sich die Ausgabe von Get-ChildItem folgendermaßen anhand der Namenserweiterung von Dateien gruppieren:
Get-ChildItem | Group-Object -Property extension
Wie erwähnt, würde in diesem Fall die Liste nach keinem Attribut sortiert, also weder nach der Häufigkeit (Attribute "Count" in der Ausgabe von Group-Object) noch nach der Extension ("Name") oder den Dateiobjekten in "Group". Eine Anzeige in alphabetischer Reihenfolge der Extensionen ließe sich so erreichen:
Get-ChildItem | Sort-Object -Property extension |
Group-Object -Property extension
Bei Verwendung von Aliases und dem Verzicht auf den Parameternamen ließe sich dieser Befehl in Kurzform so schreiben:
gci | Sort extension | Group extension
Die Ausgabe würde dann zum Beispiel folgendermaßen aussehen:
Möchte man nur die Dateinamenserweiterungen sehen, die mehr als einmal vorkommen, könnte man diese mit Hilfe von Where-Object (Alias ?) filtern:
gci | Sort extension | Group extension | ? count -gt 1
Es ist nicht nur möglich, das Ergebnis eines Cmdlets nach einem Attribut zu gruppieren, vielmehr kann man dafür auch mehrere angeben:
Get-ChildItem | group extension, attributes
In diesem Beispiel würden jene Dateien zu Gruppen zusammengefasst, die nicht nur die gleiche Extension, sondern auch die gleichen Dateiattribute besitzen.
Eventlog auswerten als Anwendung
Das Gruppieren von Daten ist vor allem dann von Nutzen, wenn sie Einträge in vielfacher Ausfertigung enthalten. Dies trifft beispielsweise auf Log-Dateien zu, wo identische Events immer und immer wieder auftauchen. Dort könnte man eine kompakte Ansicht für die Auswertung von Ereignissen so erhalten:
Get-WinEvent -ProviderName Microsoft-Windows-Hyper-V-VmSwitch |
Group-Object Message | Sort Count
Dieser Aufruf ermittelt alle Log-Einträge für den virtuellen Switch von Hyper-V, gruppiert sie anhand der Nachricht und sortiert diese nach der Häufigkeit ihres Vorkommens.
Wie man bei dieser Ausgabe sieht, wird die Darstellung bei derart umfangreichen Daten sehr schnell unübersichtlich. Dazu trägt vor allem die Spalte Group bei, welche die Datensätze enthält, die man zuvor an Group-Object übergeben hat. Sie liegen als Array vor.
Array der gruppierten Einträge aufspalten
Im Fall einer Dateiliste, wie sie obiges Beispiel mit Get-ChildItem liefert, versammeln sich in jeder Gruppe alle Dateiobjekte mit der gleichen Endung, und zwar mit den von gci angezeigten Eigenschaften.
Eine einfache Möglichkeit, den Inhalt des Arrays bei der Darstellung aufzuspalten, besteht darin, jede Gruppe durch eine Schleife laufen zu lassen und ihre Elemente einzeln auszugeben:
Get-ChildItem | Group-Object -Property extension |
%{"==> $($_.Name) $($_.count)", $_.Group}
Wesentlich eleganter ist eine Lösung unter Einsatz von Out-GridView. Dieses Cmdlet zeigt Datensätze in einer Tabelle auf der grafischen Oberfläche an. Ruft man es mit dem Parameter PassThru auf, dann reicht es die markierten Zeilen über die Pipe an weitere Cmdlets durch:
Get-ChildItem | Group-Object -Property extension |
Out-GridView -PassThru | Select -ExpandProperty Group
Hebt man in diesem Beispiel die Extension .xml hervor und klickt auf OK, dann expandiert anschließend der Aufruf von Select den Inhalt der Gruppe.
Gruppierte Daten ausblenden
Oft möchte man aber nur wissen, wie oft eine bestimmte Eigenschaft insgesamt vorkommt, also etwa die Häufigkeit eines Events in der Log-Datei.
Die zu Gruppen zusammengefassten Nachrichten interessieren dann eigentlich nicht. In diesem Fall ruft man Group-Object mit dem Schalter NoElement auf.
Transformation zu Hash-Tabelle
Group-Object unterstützt alternativ den Parameter AsHashTable. Er sorgt dafür, dass die gruppierten Daten als Hash-Tabelle zurückgegeben werden, wobei die Eigenschaft, anhand derer die Gruppierung erfolgt, als Schlüssel dient. In diesem Beispiel wäre dies Extension:
$ext = Get-ChildItem | Group-Object -Property Extension -AsHashTable -AsString
Es empfiehlt sich diese Option zusammen mit AsString zu verwenden, um sicherzustellen, dass beispielsweise numerische Daten konvertiert werden.
Anschließend kann man sich über die Punkt-Notation anzeigen lassen, welche Dateiobjekte zu einer bestimmten Erweiterung gehören:
$ext.".ps1"
Täglich Know-how für IT-Pros mit unserem Newsletter
Verwandte Beiträge
- Hyper-V Switch mit PowerShell erstellen, verwalten und löschen
- PowerShellGet-Modul aktualisieren, auf PSResourceGet umsteigen
- Adressbücher in Exchange Online anlegen und pflegen
- BitLocker aktivieren mit manage-bde, PowerShell oder WMI
- WhatIf, Confirm und Force: Ausführung von PowerShell-Cmdlets steuern
Weitere Links