Select-String: In Dateien suchen mit PowerShell

    Kostenloses eHandbook: Überblick und Praxistipps zu vSphere 6.5. Scripting mit PowerCLI 6.5, neue HA-Features und FT nutzen, u.v.m. Download »

    (Anzeige)

    Windows besitzt mit find und findstr bereits 2 Kommandozeilen-Tools, mit denen man Textdateien durchsuchen kann. Das PowerShell-eigene Mittel für diesen Zweck ist indes Select-String, das gegenüber den alten Dienstprogrammen einige wesentliche Vorteile bietet. Da die PowerShell nicht nur eine Script-Umgebung, sondern auch eine interaktive Shell ist, empfiehlt sich Select-String als mächtigere Alternative zu den bisherigen Kommandozeilen-Tools.

    Während find ein mager ausgestattetes Relikt aus DOS-Zeiten ist, implementiert findstr immerhin die wichtigsten Funktionen von grep unter Windows. Die PowerShell geht jedoch mit Select-String über die Möglichkeiten der beiden genannten Tools hinaus, unter anderem aufgrund einer vollwertigen Implementierung von regulären Ausdrücken. Zusätzlich bietet es die generellen Vorteile eines Cmdlets, die in einer engen Integration mit anderen Mechanismen der PowerShell bestehen.

    Sinnvolle Vorgabewerte

    In seiner einfachsten Form besteht der Aufruf von Select-String darin, dass man ihm einen Dateinamen (bzw. ein Muster für Dateinamen unter Verwendung von Wildcards) sowie die zu suchende Zeichenkette übergibt:

    Select-String -path index.html -pattern "Home"

    In diesem Fall erfolgt die Ausgabe aller Zeilen, die Fundstellen enthalten, auf stdout, und zwar inklusive Zeilennummer. Der Vergleich zwischen dem Suchbegriff und dem Inhalt der Datei erfolgt standardmäßig ohne Rücksicht auf Groß- und Kleinschreibung, ein Fortschritt gegenüber den alten Tools, bei denen man dafür immer den Schalten /i angeben muss. Hier ist es umgekehrt, die eher seltene Suche, die zwischen Groß- und Kleinschreibung unterscheidet, muss man explizit über den Schalter -CaseSensitive aktivieren.

    Der Wert des Parameter -pattern wird grundsätzlich als regulärer Ausdruck interpretiert. Für eine einfache Suche nach einer Zeichenkette wie im obigen Beispiel kann man stattdessen den Parameter -SimpleMatch verwenden:

    Select-String -path index.html -SimpleMatch "Home"

    Inverse Suche mit -NotMatch

    Das grep-Äquivalent in Powershell unterstützt über -NotMatch auch eine inverse Suche, bei der alle Zeilen gefunden werden sollen, die das Suchmuster nicht enthalten. Eine weitere Eingrenzung der Suche lässt sich erreichen, indem man bestimmte Dateien ausschließt, wenn man für den Parameter -path Wildcards verwendet:

    Select-String -path *.* -exclude *.pdf,*.zip -Pattern "DO.*=" -NotMatch

    Suche in Unterverzeichnissen nur mit Get-ChildItem

    In diesem Fall würden im aktuellen Verzeichnis alle Dateien mit Ausnahme von ZIP-Archiven und PDFs durchsucht. Im Gegensatz zu find und findstr ist Select-String nicht in der Lage, rekursiv die Dateien in Unterverzeichnissen zu durchsuchen. Wenn man das möchte, muss man sich weiterer Powershell-Mittel bedienen, indem man den Output von Get-ChildItem über eine Pipe an Select-String weiterleitet:

    Get-ChildItem *.* -exclude *.pdf -recurse | Select-String -Pattern "DO.*="

    Da die Auswahl der Dateien vollständig über Get-ChildItem erfolgt, kann sich der Aufruf von Select-String in diesem Fall auf die Übergabe des Suchmusters beschränken.

    Suchergebnisse in Form von MatchInfo-Objekten

    Im Unterschied zu rein textorientierten Tools wie find gibt ein Cmdlet wie Select-String Objekte zurück, im konkreten Fall vom Typ MatchInfo. Sie bieten eigene Methoden und Eigenschaften, die eine weitergehende Auswertung des Ergebnisses erlauben als bloß flacher Text. Leitet man die Ausgabe von Select-String an Get-Member weiter, dann erhält man eine Liste aller Methoden und Eigenschaften.

    Verwendung von MatchInfo-Eigenschaften

    Letztere sind beispielsweise interessant, um die Ausgabe des Cmdlets zu verändern, wenn man mit der relativ unübersichtlichen Anzeige von Pfad plus Dateiname plus Zeilennummer plus Zeile nicht zufrieden ist (der Parameter -Context gibt zusätzlich die umgebenden Zeilen aus). So würde etwa

    Select-String -path index.html -SimpleMatch "Home" | select FileName, LineNumber

    nur den Dateinamen und die Zeilennummer anzeigen, wo das Suchmuster gefunden wurde. Eine weitere Eigenschaft namens Matches ist besonders praktisch, wenn man komplexere reguläre Ausdrücke verwendet. In diesem Fall kann man oft nicht sicher sein, auf welche Zeichenketten sie tatsächlich zutreffen. In diesem Fall würde

    Select-String -path *.* -Pattern "DO.*=" | select Matches

    genau diese Übereinstimmungen anzeigen. Per Voreinstellung sieht man dabei aber nur den ersten Treffer pro Zeile. Um alle zu erhalten, muss man den Schalter -AllMatches hinzufügen.

    String-Manipulationen mit den Fundstellen

    Da sich die Ergebnisse von Select-String an alle möglichen Cmdlets weiterreichen lassen, ergeben sich dadurch fast unbegrenzte Möglichkeiten der Weiterverarbeitung. Das beginnt mit der Formatierung der Ausgabe, indem man diese etwa durch Format-List schickt und dadurch eine wesentlich übersichtlichere Ausgabe erhält. Natürlich stehen auch alle Funktionen für die String-Manipulation zur Verfügung, um die gefundenen Textstellen zu verändern:

    select-string -path *.cmd -pattern "do.*=" | foreach {$_.ToString().ToLower()}

    In diesem Beispiel wird die Ausgabe in Kleinbuchstaben konvertiert, man könnte aber etwa genauso einen Substring extrahieren oder sie mit einer anderen Zeichenkette zusammenfügen.

    Keine Kommentare