Select-String: In Dateien suchen mit PowerShell


    Tags: , ,

    Suche in Dateien mit PowerShellWindows besitzt mit find und findstr bereits zwei Kommando­zeilen-Tools, mit denen man Text­dateien durch­suchen kann. Das PowerShell-Äquivalent dafür diesen Zweck ist Select-String, das gegenüber den alten Dienst­programmen einige Vorteile bietet. Dazu gehört eine vollwertige Implementierung von regulären Ausdrücken.

    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.

    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. Dies ist 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 anpassen

    Im Unterschied zu rein textorientierten Tools wie find gibt ein Cmdlet wie Select-String Objekte zurück, im konkreten Fall vom Typ MatchInfo.

    Wenn man mit der relativ unübersichtlichen Anzeige von Pfad plus Dateiname plus Zeilennummer plus Zeile nicht zufrieden ist, dann kann man die gewünschten Eigenschaften gezielt mit Select-Object auswählen. 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.

    Über den Parameter -Context könnte man zusätzlich die Zahl der umgebenden Zeilen bestimmen.

    Verwendung von MatchInfo-Eigenschaften

    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 -expand 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.

    Täglich Know-how für IT-Pros mit unserem Newsletter

    Wir ver­wenden Ihre Mail-Adresse nur für den Ver­sand der News­letter.
    Es erfolgt keine per­sonen­be­zogene Auswertung.

    Bild von Wolfgang Sommergut

    Wolfgang Sommergut hat lang­jährige Erfahrung als Fach­autor, Berater und Kon­ferenz­sprecher zu ver­schie­denen Themen der IT. Da­ne­ben war er als System­ad­mi­ni­stra­tor und Con­sultant tätig.
    // Kontakt: E-Mail, XING, LinkedIn //

    Ähnliche Beiträge

    Weitere Links

    3 Kommentare

    Guten Morgen,

    ich habe eine Frage und zwar, ich habe eine Textdatei mit sehr vielen Wörtern in ca.300 Zeilen, und ich möchte dass mir nur 2 Bestimmte Wörter aus einer Zeile ausgelesen werden, wie funktioniert dass?

    Guten Tag,

    Ich möchte das Gleiche wissen. Ich kann die Zeile "selecten" in welcher der gesuchte Begriff ist. Jedoch möchte ich nur ein Wort als Ausgabe haben.
    Wie funktioniert das?

    Die Verwendung von MatchInfo-Eigenschaften kannte ich bisher nicht - danke für den Hinweis.