Zum Inhalt springen
Allin

Zeilen nach einem Muster filtern — ohne Kommandozeile

Veröffentlicht am 7.8.2026 · 10 Min. Lesezeit · Text- & Sprach-Tools

Daniel Okonkwo

Daniel OkonkwoFront-end-Entwickler und Tech-Redakteur bei Allin

Web-Performance · Dateiformate

Anhand von 3 Quellen geprüft

Profil ansehen
Kurz gesagt

filter-lines teilt deinen Text an Zeilenumbrüchen, prüft jede Zeile auf eine Teilzeichenkette und behält oder verwirft sie. Verglichen wird mit String.prototype.includes gegen einen wörtlichen Begriff — hinter dem Feld steckt keine Regex-Maschine. ^ERROR in ein Log getippt ergab nichts; ERROR|WARN ebenso wenig; [a-z]+ ebenso wenig. Jedes lieferte ein leeres Ausgabefeld, ohne Fehlermeldung und ohne Hinweis, dass das Muster wörtlich gelesen wurde — genau dieses Verhalten sollte man vorher kennen. Das Gegenteil gilt auch und ist tröstlicher: Ein ungültiger regulärer Ausdruck ist hier harmlos, weil es kein regulärer Ausdruck ist. Eine einzelne öffnende Klammer getippt behielt die Zeile, die eine enthält, genau wie gewünscht. „Groß/Klein ignorieren“ ist voreingestellt an: Nach apple gefiltert blieb die Zeile APPLE juice ebenso stehen wie apple pie; grep im Terminal unterscheidet standardmäßig Groß- und Kleinschreibung, dieses Werkzeug nicht — ein Unterschied, den man im Kopf behalten sollte. Die Aktion bietet „Treffer behalten“ und „Treffer entfernen“, was grep und grep -v entspricht. Ein leerer Begriff gibt deinen Text unverändert zurück, nicht nichts. Zwei Details aus den Läufen: Der Entfernen-Modus behält Leerzeilen, denn eine Leerzeile enthält deinen Begriff nicht, ein gefiltertes Log kommt also mit den Lücken der entfernten Zeilen zurück; und die gesamte Ausgabe wird mit einfachen Zeilenvorschüben zusammengefügt, eine Windows-Datei verliert unterwegs also ihre Wagenrückläufe.

Das ist grep für Menschen, die grep nicht benutzen — mit einem wichtigen Unterschied: Gesucht wird eine reine Teilzeichenkette, ein echter regulärer Ausdruck liefert also ein leeres Feld und keine Fehlermeldung. Jede Aussage hier wurde durch Ausführen des Werkzeugs geprüft.

Was grep tut und welche Hälfte davon hier ist

grep liest einen Text Zeile für Zeile, prüft jede Zeile gegen ein Muster und gibt die passenden Zeilen aus. Die POSIX-Spezifikation definiert es so und definiert das Muster als regulären Ausdruck — eine kleine Sprache, in der ein Zirkumflex „Zeilenanfang“ heißt, ein senkrechter Strich „oder“, eckige Klammern „irgendeines dieser Zeichen“ und ein Plus „ein- oder mehrmals das Vorhergehende“. Die Umkehroption dreht den Test um und druckt die Zeilen, die nicht passten. Die Idee ist rund vierzig Jahre alt und immer noch der schnellste Weg, eine Frage an eine Logdatei zu stellen.

filter-lines setzt die Schleife und die Umkehroption um und hört dort auf. Die Mustersprache ist nicht umgesetzt, und vor allem ist sie nicht halb umgesetzt: Der eingetippte Begriff wird als Zeichenfolge verglichen, ganz und unverändert. Das ist ein legitimer Entwurf für ein Feld auf einer Webseite — die meisten, die eine Liste filtern, wollen Zeilen mit dem Wort Rechnung, keine Grammatik —, aber es heißt, dass beide Werkzeuge dieselbe Eingabe verschieden beantworten, und das Werkzeug, das dabei danebenliegt, sagt es nie.

Das leere Feld und warum es leer ist

Drei Muster liefen gegen dasselbe siebenzeilige Log. ^ERROR ergab nichts, obwohl zwei Zeilen mit ERROR beginnen, weil keine Zeile einen wörtlichen Zirkumflex gefolgt von den Buchstaben E, R, R, O, R enthält. ERROR|WARN ergab nichts, obwohl das Log von jedem eines hat, weil keine Zeile einen wörtlichen senkrechten Strich zwischen diesen beiden Wörtern enthält. [a-z]+ ergab nichts, aus demselben Grund: Keine Zeile enthält eine eckige Klammer. In jedem Fall war das Ausgabefeld schlicht leer. Nichts wurde hervorgehoben, nichts gemeldet, und nichts deutete an, dass der Begriff anders gelesen worden war als gemeint.

Das ist der Fehlermodus, auf den es ankommt, und er ist das Gegenteil dessen, was der Ausdruck „ungültige Regex“ nahelegt. Ein fehlerhaftes Muster ist der sichere Fall. Eine einzelne öffnende Klammer getippt — bei der eine Regex-Maschine einen Fehler über eine nicht geschlossene Gruppe werfen würde — behielt die Zeile mit einer Klammer und gab sie zurück. Ebenso ein einzelner Punkt, der in der Regex-Sprache „irgendein Zeichen“ heißt und hier „ein Punkt“: Bei einer Liste mit a.b und aXb kam nur a.b zurück. Ertappst du dich dabei, Regex-Syntax in dieses Feld zu tippen, ist der zu übende Reflex, die Ausgabe anzusehen und zu fragen, ob ein leeres Ergebnis plausibel ist — denn das Werkzeug fragt es nicht für dich.

Groß- und Kleinschreibung, Akzente und das Leerzeichen, das du nicht tippen wolltest

„Groß/Klein ignorieren“ ist ab Werk an und schreibt vor dem Vergleich sowohl die Zeile als auch den Begriff klein. Eine fünfzeilige Obstliste nach apple gefiltert behielt apple pie, APPLE juice und pineapple tart; mit ausgeschaltetem Schalter fiel APPLE juice weg und die anderen zwei blieben. Die pineapple-Zeile erinnert daran, dass dies ein Teilzeichenketten- und kein Worttest ist: apple steckt in pineapple, die Zeile passt also, und es gibt keine Option „ganzes Wort“, die das verhindert. Brauchst du Wortgrenzen, nimm die umgebenden Leerzeichen in den Begriff auf und nimm hin, dass dir das Wort am Zeilenanfang oder -ende entgeht.

Aus denselben Läufen kamen zwei kleinere Fallen. Ein führendes Leerzeichen im Begriff gehört zum Begriff: Dieselbe Liste nach Leerzeichen plus apple gefiltert ergab nichts, weil keine Zeile an der geprüften Stelle ein Leerzeichen vor diesem Wort hat. Und Akzente folgen der Regel aus dem Duplikat-Artikel: Ein Begriff, dessen Akzentbuchstabe als Buchstabe plus kombinierendes Zeichen geschrieben ist, fand nichts in einer Liste, deren Akzentbuchstabe ein einzelner Codepunkt ist, obwohl beide im Suchfeld identisch aussehen. Beides läuft auf dieselbe Disziplin hinaus: Was du getippt hast, wird exakt so verglichen, wie du es getippt hast, samt der Teile, die du nicht siehst.

Der Entfernen-Modus hinterlässt Löcher

Stell die Aktion auf „Treffer entfernen“, und das Werkzeug wirft jede Zeile mit deinem Begriff weg und behält alles andere — auch die Leerzeilen, denn eine Leerzeile enthält deinen Begriff nicht. Lass es über ein Log mit einer Leerzeile zwischen zwei Einträgen laufen, und die Leerzeile ist danach noch da. Das ist kein Fehler, sondern die ehrliche Lesart der Anweisung, aber das Ergebnis sieht selten so aus, wie man es erwartet hat, und eine gefilterte Datei mit einem Dutzend verwaister Lücken liest sich lästig. Die Abhilfe ist ein weiterer Schritt: remove-blank-lines über die Ausgabe laufen lassen.

Noch ein Verhalten, auf das man bauen kann: Ein leerer Begriff gibt deinen Text unverändert zurück, kein leeres Ergebnis. Das klingt selbstverständlich, aber die Gegenlesart — kein Begriff, also passt nichts, also kommt nichts heraus — wäre ebenso vertretbar und würde deine Eingabe jedes Mal stillschweigend leeren, wenn du das Feld für eine neue Suche löschst. Das Werkzeug wählt den sichereren Zweig, und das wurde geprüft: Mit leerem Feld kamen alle fünf Zeilen der Testliste zurück.

Was tun, wenn du wirklich ein Muster brauchst

Die meisten Musterfragen lassen sich als Teilzeichenkettenfragen umschreiben. „Zeilen, die mit einem Code beginnen“ wird zu „Zeilen, die diesen Code enthalten“ — lockerer, aber bei einem Log, in dem der Code ohnehin nur am Anfang steht, meist ausreichend. „Eines von zwei Wörtern“ wird zu zwei Durchgängen — nach dem ersten filtern, Ergebnis notieren, das Original nach dem zweiten filtern —, weil es keine Alternative gibt. „Ein Zeichenbereich“ wird meist zu mehreren Durchgängen oder gleich zu einem anderen Werkzeug. Braucht die Antwort wirklich eine Grammatik, lautet der ehrliche Rat: Ein Textfeld im Browser ist das falsche Instrument, das richtige ist ein Terminal oder ein Texteditor mit Regex-Suche.

Ein Vorbehalt zum Schwesterwerkzeug. find-and-replace nimmt auf derselben Website ebenfalls einen wörtlichen Begriff: Es escapet jedes Zeichen mit Sonderbedeutung, bevor es sein Muster baut — im Quelltext nachgelesen und bestätigt. Wolltest du damit einen Regex-Filter nachbauen, geht das also nicht. Die beiden Werkzeuge sind untereinander konsistent, das ist die gute Nachricht; keines von beiden ist grep, das ist die Nachricht, die du vorher brauchtest.

In das Feld „Enthält“ getippte Begriffe und was das Werkzeug tatsächlich zurückgab
Getippter BegriffWas zurückkommtWarum
apple, „Groß/Klein ignorieren“ an (Voreinstellung)apple pie, APPLE juice und pineapple tartBeide Seiten werden kleingeschrieben, und geprüft wird die Teilzeichenkette, nicht das ganze Wort
apple, „Groß/Klein ignorieren“ ausnur apple pie und pineapple tartAPPLE juice enthält die exakt getippten Zeichen nicht mehr
^ERROR auf einem Log, dessen erste zwei Zeilen mit ERROR beginnenLeere Ausgabe, keine FehlermeldungKeine Zeile enthält einen wörtlichen Zirkumflex gefolgt von diesen fünf Buchstaben
ERROR|WARN auf demselben LogLeere AusgabeEs gibt keine Alternative; der senkrechte Strich ist nur ein zu suchendes Zeichen
Eine einzelne öffnende KlammerDie Zeile mit einer Klammer — es funktioniertEin ungültiger regulärer Ausdruck ist der sichere Fall, denn es wird keiner kompiliert
Ein einzelner Punkt, auf einer Liste mit a.b und aXbnur a.bDer Punkt trifft einen Punkt, nicht irgendein Zeichen
Ein leeres Feld „Enthält“Der ganze Text, unverändertDas Werkzeug steigt früh aus, statt alles wegzufiltern
Jeder Begriff, im Modus „Treffer entfernen“, auf einem Text mit LeerzeilenDie Leerzeilen überlebenEine Leerzeile enthält den Begriff nicht, ist also kein zu entfernender Treffer
Zeilen filternBehalte oder entferne die Zeilen, die ein Wort oder einen Satz enthalten.Tool ausprobieren

Häufige Fragen

Kann ich im Feld „Enthält“ einen regulären Ausdruck verwenden?
Nein. Der Begriff wird wörtlich verglichen, Zeichen für Zeichen, ohne Mustersprache dahinter. Das wurde an drei gewöhnlichen Mustern geprüft — einem Zeilenanfangsanker, einer Alternative und einer Zeichenklasse — und alle drei lieferten ein leeres Ausgabefeld ohne Meldung. Zu verinnerlichen ist, dass eine falsche Antwort hier genau wie eine richtige Antwort „nichts passte“ aussieht: Behandle ein leeres Ergebnis als Frage, nicht als Tatsache, tippe den Begriff ohne seine Syntaxzeichen erneut und sieh, ob Zeilen erscheinen.
Wie behalte ich nur die Zeilen, die mit etwas beginnen?
Zeilenanfang lässt sich hier nicht verlangen, denn es gibt keinen Anker. In der Praxis genügt die Teilzeichenketten-Variante meist: nach dem Code oder Präfix selbst filtern und Zeilen hinnehmen, die ihn woanders enthalten. Ob das vertretbar ist, hängt von deinen Daten ab, und du findest es billig heraus — einmal filtern, dann denselben Begriff im Entfernen-Modus laufen lassen und ansehen, was herauskam. Enthält der entfernte Haufen nichts Gewolltes, war die lockere Variante in Ordnung. Brauchst du den Anker wirklich, ist ein Texteditor mit Regex-Suche das passende Werkzeug.
Unterscheidet der Filter Groß- und Kleinschreibung?
Standardmäßig nicht. „Groß/Klein ignorieren“ ist beim Laden der Seite an — das Gegenteil der grep-Voreinstellung und das Gegenteil dessen, was ein Terminal-Gewohnter erwartet. Schalte es im selben Feld aus, wenn du die Unterscheidung brauchst: Eine Obstliste nach apple gefiltert behielt mit eingeschaltetem Schalter eine Zeile APPLE juice, und ausgeschaltet fiel diese Zeile weg, während die zwei kleingeschriebenen blieben. Gefaltet wird schlicht sprachunabhängig: akzentuierte Großbuchstaben werden korrekt behandelt, aber es geschieht nichts Besonderes für eine bestimmte Sprache.
Warum hat meine gefilterte Ausgabe Lücken?
Weil du „Treffer entfernen“ benutzt hast und dein Text Leerzeilen enthielt. Eine Leerzeile enthält deinen Begriff nicht, das Werkzeug behält sie also, und sie bleibt genau dort, wo sie war — jetzt umgeben von dem Platz, den die entfernten Zeilen einnahmen. remove-blank-lines über das Ergebnis laufen zu lassen schließt sie alle in einem Durchgang. Verkettest du mehrere Filter, mach die Leerzeilen-Bereinigung einmal am Ende statt nach jedem Schritt, denn jeder Entfernen-Durchgang öffnet neue Lücken.
Sagt mir das Werkzeug, wie viele Zeilen passten?
Es wird keine Zahl angezeigt; du bekommst die passenden Zeilen und sonst nichts. Brauchst du die Anzahl, führt der kürzeste Weg über einen Zeilenzähler auf dem Ergebnis oder über count-occurrences auf dem Originaltext mit demselben Begriff — im Hinterkopf, dass es Vorkommen zählt und eine Zeile deinen Begriff zweimal enthalten kann, die beiden Zahlen also berechtigt auseinandergehen dürfen. Willst du eigentlich die Zahl und nicht die Zeilen, ist count-occurrences der bessere Ausgangspunkt.

Artikel, die dich interessieren könnten

Alle Ratgeber
RatgeberSuchen und Ersetzen: die Regex-Fallen, eine nach der anderen vorgeführtGierig gegen genügsam an derselben Zeichenkette, der Punkt, der Zeilenumbrüche überspringt, $& und $$ in der Ersetzung, eine wiederverwendete /g-Regex, die stillschweigend eine Zeile auslässt, und warum /i vom türkischen i nichts weiß. Jeder Fehlschlag in Node ausgeführt, mit einer Zähl-dann-Ersetze-Routine, die sie einfängt.AnleitungZeilen nummerieren, damit mehrere Leute denselben Text prüfen könnenDie Nummerierung beginnt bei 1 und lässt sich nicht auf 0 setzen, ausgerichtet wird mit Leerzeichen statt Nullen, und das Entfernen macht acht der elf Trennzeichen rückgängig, ohne die Einrückung anzutasten. Was es weiterhin nicht kann: deine Zahlen von seinen unterscheiden.ErklärungEmoji sind schwerer, als sie aussehen: warum es für „einfach die Emoji entfernen“ keine Einzeiler-Antwort gibtEin sichtbares Emoji kann ein Codepunkt sein oder vierzehn UTF-16-Einheiten. Wir haben drei verbreitete reguläre Ausdrücke auf einen echten Satz losgelassen, und jeder ist anders gescheitert — einer löschte die Ziffern. Hier steht, warum, welche Unicode-Eigenschaft welche Frage beantwortet, und welche Graphemcluster-Regel wirklich funktioniert.ErklärungWo eine Zeile brechen darf: der Unicode-Algorithmus hinter jedem umbrochenen Absatz„An Leerzeichen umbrechen“ scheitert in den meisten Schriftsystemen der Welt. UAX #14 gibt jedem Zeichen eine Zeilenumbruchklasse; wir haben unsere in Unicode 17.0.0 nachgeschlagen und eine konforme Implementierung über geschützte Leerzeichen, weiche Trennstriche, Nullbreiten-Leerzeichen, URLs, Japanisch und Thai laufen lassen.RatgeberZwischen Listenformaten konvertieren, ohne Daten zu verlieren: die Anführungsregeln, die niemand liestAus einer Liste mit Zeilenumbrüchen eine Kommaliste zu machen ist trivial, bis ein Eintrag ein Komma enthält. Die Anführungsregeln von RFC 4180, warum ein CSV-Feld einen Zeilenumbruch enthalten darf, warum europäische Tabellenkalkulationen das Semikolon verwenden und was ein leerer Eintrag mit dem Hin- und Rückweg macht — jeder Fall ausgeführt und abgedruckt.RatgeberEine aus Tabelle oder PDF eingefügte Liste bereinigenEin Einfügen bringt unsichtbare Zeichen mit: geschützte Leerzeichen, weiche Trennstriche, Nullbreiten-Leerzeichen, Tabs und CRLF. Vier Bereinigungswerkzeuge liefen über jedes davon — und sie verwenden drei verschiedene Definitionen von Leerraum.

Ähnliche Tools

Alles hier beschreibt, was diese Werkzeuge heute tun — geprüft, indem ihre eigenen Transformationen mit genau den in jedem Artikel abgedruckten Eingaben ausgeführt wurden — und nicht, was ein Standard einem Textwerkzeug vorschreibt. Zeilenweise Textverarbeitung hat keine einzige Instanz: Was als Leerraum zählt, ob zwei akzentuierte Zeilen dieselbe Zeile sind und wo eine URL im Fließtext endet, entscheidet jedes Programm anders, in das du je etwas einfügen wirst. Wo ein Werkzeug einen Fall falsch behandelt, wird das offen gesagt statt umgangen. Bevor du irgendetwas davon über eine Liste laufen lässt, die du nicht neu exportieren kannst, lauf über eine Kopie und vergleiche die Zeilenzahl an beiden Enden.

Quellen

Hast du einen Fehler in diesem Artikel entdeckt?