Grep mit der PowerShell

Im letzten Blogeintrag haben wir uns angesehen, wie man den Windows CMD Befehl more beziehungsweise den optimierten Linux Befehl less mit der PowerShell abbilden kann.
 
In diesem Blogeintrag schauen wir uns an, wie man den genialen Linux bash Befehl grep mit PowerShell Befehlen nachbilden kann.
 
Der Begriff grep steht für global/regular expression/print (Danke wikipedia 🙂 ) und dient dem Suchen und Filtern von Dateien und Befehlsausgaben. Gerade bei großen Logdateien kann man so sehr schnell die relevanten Zeilen finden.
 
Der Befehl grep war früher (zu Zeiten, als es noch keine PowerShell gab) für mich der Hauptgrund, unter Windows Cygwin zu nutzen. Cygwin ermöglicht es, Linux bash Befehle wie z.B. grep unter Windows zu auszuführen. Mit der modernen PowerShell ist dies nicht mehr notwendig.
 
In der PowerShell nutzt man 2 Befehle, um den grep Befehl abzubilden.
 
Zum einen den Befehl Out-String -Stream. Dieser sorgt dafür, dass die Ausgabe des vorherigen Befehls sicher zeilenweise weitergegeben wird. Ansonsten könnten wir nicht zeilenweise die Ausgabe durchsuchen
 
Als Beispiel nehme ich die Ausgabe der Hilfe und zähle die Anzahl der enthaltenen Zeilenobjekte.
 
(Get-Help Get-ChildItem -Detailed).count  gibt als Ergebnis 0 aus. Die ganze Ausgabe der Hilfe ist eine lange, mit Sonderzeichen formatierte Zeile.
 
(Get-Help Get-ChildItem -Detailed |Out-String -Stream).count gibt als Ergebnis 159 aus. Immer nach dem Sonderzeichen "Zeilenumbruch" bzw. "CRLF" wird eine neue Zeile erzeugt.
 
(Get-Help Get-ChildItem -Detailed).count

(Get-Help Get-ChildItem -Detailed |Out-String -Stream).count
159

Zum anderen der Befehl Select-String. Mit diesem Befehl kann ich einzelne Strings nach Wörtern oder Mustern durchsuchen.
 
Über den Parameter -Pattern gebe ich das zu suchende Wort, die Wortliste oder das Muster an (Hier können auch reguläre Ausdrücke genutzt werden - darauf möchte ich nicht weiter eingehen. Das passende Buch von O`Reilly "Mastering Regular Expressions" hat 544 Seiten)
 
Mit dem Parametern -SimpleMatch teile ich der PowerShell mit, dass der Pattern kein regulärer Ausdruck ist.
Mit dem Parameter -CaseSensitive beachtet die PowerShell, ob die Buchstaben groß oder kleingeschrieben sind.
 
Als Beispiel nehmen wir wieder unseren Get-Help Befehl von vorhin.
 
Ich möchte alle Zeilen finden, in denen das einzelne Wort "Cert" vorkommt.
 
Get-Help Get-ChildItem -Detailed | Out-String -Stream | Select-String -Pattern "Cert" -SimpleMatch
 
Get-Help Get-ChildItem -Detailed |Out-String -Stream |Select-String -Pattern "Cert" -SimpleMatch

    certificate store.
    Example 6: Get all certificates in a certification drive that have code-signing authority
    PS C:\>Get-ChildItem -Path "Cert:\*" -Recurse -CodeSigningCert
    This command gets all of the certificates in the Windows PowerShell Cert: drive that have...
    The first command imports the Microsoft.PowerShell.Security module into the session. This module includes the Cert...
    The second command uses the Get-ChildItem cmdlet. The value of the Path parameter is the Cert: drive. 
    CodeSigningCertificate parameter is a...

Wenn ich mehrere möglicher Suchwörter habe, dann erstelle ich eine kurze Stringliste

$pattern = "Cert","HKLM"

Get-Help Get-ChildItem -Detailed |Out-String -Stream |Select-String -Pattern $pattern -SimpleMatch

$pattern = "Cert","HKLM"
Get-Help Get-ChildItem -Detailed |Out-String -Stream |Select-String -Pattern $pattern -SimpleMatch

    certificate store.
    PS C:\>Get-ChildItem -Path "HKLM:\Software"
    Example 6: Get all certificates in a certification drive that have code-signing authority
    PS C:\>Get-ChildItem -Path "Cert:\*" -Recurse -CodeSigningCert
    This command gets all of the certificates in the Windows PowerShell Cert: drive that have code-signing authority.
    The first command imports the Microsoft.PowerShell.Security module into the session. This module includes the Cert ...
    The second command uses the Get-ChildItem cmdlet. The value of the Path  parameter is the Cert: drive ...
    ...

Ein weiteres Beispiel aus der IT Administrations Praxis sind die DHCP Server logs.

Frage: Der Client AR-IT mit der MAC Adresse "90dd5d8e6d34" und der IP 10.12.1.29 verhält sich komisch. Lieber DHCP Server: weißt du irgendwelche Details?

Lösungsweg: 

$pattern = "AR-IT","90dd5d8e6d34","10.12.1.29"   # Eins von den dreien soll vorkommen

Get-Content C:\Windows\System32\dhcp\DhcpSrvLog-Die.log | Out-String -Stream |Select-String -Pattern $pattern -SimpleMatch

PS C:\> $pattern = "AR-IT","90dd5d8e6d34","10.12.1.29"
PS C:\> Get-Content C:\Windows\System32\dhcp\DhcpSrvLog-Die.log | Out-String -Stream |Select-String -Pattern $pattern -SimpleMatch

11,02/04/20,00:02:09,Erneuern,10.12.1.29,AR-IT.ad.firma.de,90DD5D8E6D34,,3564366365,0,,,,,,,,,0
11,02/04/20,00:02:09,Erneuern,10.12.1.29,AR-IT.ad.firma.de,90DD5D8E6D34,,3564366365,0,,,,,,,,,0
11,02/04/20,00:06:56,Erneuern,10.12.1.29,AR-IT.ad.firma.de,90DD5D8E6D34,,3597920797,0,,,,,,,,,0
11,02/04/20,00:06:56,Erneuern,10.12.1.29,AR-IT.ad.firma.de,90DD5D8E6D34,,3597920797,0,,,,,,,,,0
11,02/04/20,00:08:26,Erneuern,10.12.1.29,AR-IT.ad.firma.de,90DD5D8E6D34,,3631475229,0,,,,,,,,,0
11,02/04/20,00:08:26,Erneuern,10.12.1.29,AR-IT.ad.firma.de,90DD5D8E6D34,,3631475229,0,,,,,,,,,0
11,02/04/20,00:10:25,Erneuern,10.12.1.29,AR-IT.ad.firma.de,90DD5D8E6D34,,3665029661,0,,,,,,,,,0
11,02/04/20,00:10:25,Erneuern,10.12.1.29,AR-IT.ad.firma.de,90DD5D8E6D34,,3665029661,0,,,,,,,,,0
11,02/04/20,00:11:35,Erneuern,10.12.1.29,AR-IT.ad.firma.de,90DD5D8E6D34,,3698584093,0,,,,,,,,,0

Antwort: O.K., der DHCP Client Dienst vom AR-IT spinnt und fragt alle 1-4 Minuten nach einer neuen IP Adresse. Reboot tut gut. Problem ist gelöst 🙂

 

2 Kommentare

  • Antworten Karl |

    Hallo Boris, danke für den Blog-Beitrag. Ich möchte nur anmerken, dass grep weder mit Linux noch mit bash etwas zu tun hat. grep gibt es für alle Unix-Derivate (also nicht nur Linux, sondern auch zB BSD, Solaris, …) und er ist wohl unter allen Shell-Interpretierern (also nicht nur bash, sondern auch zB ksh, zsh, tcsh, …) lauffähig.

    • Antworten Boris Birneder |

      Hallo Karl,
      danke für den Hinweis. Da hast du vollkommen recht. In der Windows Welt kennen aber viele nur den Begriff „bash“ für die UNIX-Shell, genauso wie Linux = Unix. Grüße Boris

Was denken Sie?