Zum Hauptinhalt springen

Suchgruppen

Die Variable $matches kann verwendet werden, um den gesuchten Ausdruck aus einem Text zu extrahieren. Wenn man nur einen (oder mehrere) Teile aus einem Suchmuster extrahieren möchte, sind Suchgruppen ausgesprochen nützlich. Eine Suchgruppe wird in runden Klammern angegeben und im Suchergebnis ($matches) als Schlüssel eines Hash-Arrays angezeigt. Als Beispiel ein Ausschnitt aus der Ausgabe von Ipconfig:

" IPv4-Adresse . . . . . . . . . . : 192.168.100.154" -match '(\S+).+:\s+(.+)'
True

$matches
Name  Value
----  -----
2     192.168.100.154
1     IPv4-Adresse
0.    IPv4-Adresse . . . . . . . . . . : 192.168.100.154

Die Variable $matches beinhaltet drei Schlüssel-Wertepaare. Der Wert mit dem Schlüssel-Namen 0 enthält den durchsuchten String, während in den Werten der Schlüssel 1 und 2 die gefundenen Teilgruppen stehen.

Mit Hilfe von Suchgruppen ist es möglich, Logdateien mit einem statischen Aufbau in Objekte umzuwandeln. Als Beispiel dafür soll Windowsupdate.log herhalten. Diese Datei muss ab Windows 10 mit dem Cmdlet Get-Windowsupdatelog aus Windows Tracing-Dateien (.evt) erzeugt werden.

Get-WindowsUpdateLog -LogPath $env:TEMP\windowsupdate.log
$updatelog = Get-Content -Path $env:TEMP\windowsupdate.log

Die einzelnen Zeilen des Updatelogs bestehen aus 6 Spalten, die durch Leerzeichen getrennt sind, wobei die letzte Spalte Freitext enthält, der auch Leerzeichen beinhalten kann.

"2018.05.22 10:32:51.2678421 4552 1472 Misc Test Hook uninit"

Die ersten 5 Spalten können keine Leerzeichen beinhalten. Man kann Sie daher durch den Platzhalter \S und den Quantifizierer + beschreiben.

"2018.05.22 10:32:51.2678421 4552 1472 Misc Test Hook uninit" -match '\S+'
> True
$Matches
> Name Value
> ---- -----
> 0    2018.05.22

Der reguläre Ausdruck "\S+" hat mehrer Treffer, aber $matches liefert nur den ersten Treffer zurück.

Mit Suchgruppen werden Unterausdrücke angeben, die einzeln zurückgegeben werden sollen. Alle Teile des Suchmusters, die nicht in einer Suchgruppe stehen, werden zwar zur Beschreibung des Suchmusters herangezogen, aber nicht mit ausgegeben.

"^(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(.+)" definiert für jede Spalte der Logdatei eine Suchgruppe. Hinter der Suchgruppe dürfen ein oder mehrere Leerzeichen auftreten, dargestellt durch \s+, aber die Leerzeichen werden nicht mit in die Ausgabe aufgenommen, weil sie außerhalb der runden Klammern und damit nicht in den Suchgruppen stehen. Da die letzte Spalte beliebige Zeichen enthalten darf und bis zum Ende der Zeile geht, wird das Suchmuster mit .+ beschrieben. Der Punkt steht für beliebige Zeichen bis auf Zeilenumbrüche.

$RegEx = '^(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(.+)'
"2018.05.22 10:32:51.2678421 4552 1472 Misc Test Hook uninit" -match $regex
$Matches

> Name Value
> ---- -----
> 6    Test Hook uninit
> 5    Misc
> 4    1472
> 3    4552
> 2    10:32:51.2678421
> 1    2018.05.22
> 0    2018.05.22 10:32:51.2678421 4552 1472 Misc Test Hook uninit

Für jede der Suchgruppen wird in der Hashtabelle $matches ein neues Schlüssel-Wertepaar generiert, wobei die Schlüsselnamen der Reihenfolge der Gruppen entsprechen. Wert 0 beinhaltet den durchsuchten Wert.

Aus der Variable $matches kann direkt ein Objekt erzeugt werden, allerdings ist die Zeile mit dem durchsuchten Wert überflüssig und kann mit der Methode Remove entfernt werden. Danach kann $matches direkt verwendet werden, um ein neues Objekt zu erzeugen. Um die Werte in die gleiche Reihenfolge zu bringen wie im Logfile, wird Select-Object genutzt.

$Matches.remove(0)
New-Object -TypeName PSCustomObject -Property ( $Matches ) | Select-Object '1','2','3','4','5','6'

 Mit einer Foreach-Schleife werden die einzelnen Logeinträge der Datei zeilenweise ausgewertet. Das fertige Skript sieht dann so aus:

$UpdatelogValues = Get-Content -Path $env:TEMP\windowsupdate.log -ReadCount 0
$RegEx = '^(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(.+)'
$UpdateLog = foreach ( $line in $UpdatelogValues )
{
   $null = $line -match $RegEx
   $Matches.Remove(0)
   New-Object -TypeName PSCustomObject -Property ( $Matches ) | 
      Select-Object '1','2','3','4','5','6'
}

$UpdateLog | Out-GridView

 

Image 126

Non-Capturing Groups

Stellen Sie sich jetzt vor, dass Sie mehrere, aber nicht alle Quellen (Spalte 5) aus dem Updatelog filtern möchte, z.B. Agent, Api und Downloadmanager. Sie können die drei gesuchten Werte in einer Gruppe mit Oder zusammenfassen: (Agent|Api|Downloadmanager). Um diese Gruppe nicht mit auszugeben, markieren Sie sie als Non-Capturing Group mit ?: hinter der öffnenden Klammer: 

$Regex = '^(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(?:Agent|Api|Downloadmanager)\s+(.+)'

Non-Capturing Groups sind Gruppen, die Zeichen gruppieren können, ohne sie hinterher in die Ausgabe mit aufzunehmen. 

Suchgruppe

Beispiel

Bedeutung

 

(ABC)

 

(\w+\).exe\s

Suchgruppe: ein "Untermuster" in einem Suchtext. Extra-hiert den Dateinamen. Gruppen können in Powershell aus der Variable $matches ausgelesen werden.

 

(?:ABC)

 

(?:\d{1,3}){4}

Erstellt ein Untermuster, wird aber nicht extrahiert. Wenn man Gruppen quantifizieren möchte, ohne Sie zu extrahie-ren.

Mehr zum Windows Update-Log finden Sie unter Windows Update log files.