Die klassischen Texteditoren Vim und Emacs beherrschen reguläre Ausdrücke. Damit wählen Sie Zeichen, Worte, Zeilen oder gar ganze Absätze aus und nehmen im Text ein musterbasiertes Suchen und Ersetzen vor.
Reguläre Ausdrücke – im Englischen heißen sie Regular Expressions (Regex, RE) – sind ein fundamentales, durchdachtes Konzept, das jeder Linux-Benutzer, Entwickler, Systemadministrator und Autor kennen und zumindest grundlegend beherrschen sollte. Nicht ohne Grund gehört das Thema als fester Bestandteil zu den beiden Linux-Zertifizierungen LPIC-1 und CompTIA Linux+.
In früheren Ausgaben erschienen bereits mehrere Artikel aus dem Umfeld regulärer Ausdrücke, beispielsweise zu den Grundlagen [1] oder zum automatischen Erzeugen von REs [2]. Nun schließt sich ein weiterer Artikel für den Alltag an: die praktische Anwendung von Regex am Beispiel der Texteditoren Vim und Emacs. Wir loten hierbei aus, wie die Verfügbarkeit, Nutzbarkeit und praktische Anwendbarkeit regulärer Ausdrücke beim Erstellen und Modifizieren von Text und Programmcode aussieht.
Vermutlich kennen Sie sowohl REs als solche als auch die Navigation in einem Texteditor als separate Vorgehensweisen. Das Anwenden regulärer Ausdrücke in Texteditoren oder integrierten Entwicklungsumgebungen (IDE) dagegen wird nach unserer Beobachtung nicht gelehrt. Um diesen Punkt müssen Sie sich selbst kümmern. Dabei spielen Texteditoren eine essenzielle Rolle beim Programmieren und Erstellen beziehungsweise Redigieren von Textdateien. Erst die Kombination aus beiden Vorgehensweisen versetzt Sie in die Lage, sämtliche zur Verfügung stehenden Joker auszuspielen.
Historie
Vim und Emacs haben sich als grundlegende, freie und verlässliche Werkzeuge zur Textbearbeitung längst einen Stammplatz auf unixoiden Systemen gesichert. Gerade Vi kommt als Editor in tatsächlich jeder Linux-Distribution mit. Das Beherrschen von wenigstens einem der beiden Tools ebnet Ihnen glaubhaft den Weg in den Hacker-Olymp. Alles andere gilt in Fachkreisen häufig als neumodischer Kram für Möchtegerntastendrücker und Mausschubser, die auf Kilometergeld aus sind.
Falls es bei einem Linux-Event Schneeball- oder Wasserschlachten zwischen beiden Lagern gibt, hilft es, vorab zu wissen, in welchem der beiden Teams Sie mitspielen möchten. Atom und Co. bringen selten genügend Mitglieder für eine eigene Mannschaft zustande. Unsere Präferenzen sind da ganz eindeutig: Gerold gehört seit Jahrzehnten zur Emacs-Fraktion und hat sich sein Wissen bei Richard Stallman abgeschaut. Frank setzt hingegen begeistert Vim ein, dessen Benutzung ihm Sven Guckes auf seine unverwechselbare Art nahebrachte.
Regex-Dialekte
Listet ein Werkzeug stolz das Unterstützen regulärer Ausdrücke auf, klingt das zwar grundsätzlich gut. Sie sollten aber unbedingt genauer hinsehen, was damit konkret gemeint ist. Zum einen gibt es mehrere Regex-Dialekte und Implementierungen, die sich in der Schreibweise, im Funktionsumfang und in der Interpretation von regulären Ausdrücken teilweise deutlich voneinander unterscheiden. Zum anderen geht nicht immer ganz klar aus der Dokumentation hervor, welche Regex-Variante die Standardeinstellung des jeweiligen Werkzeugs ist. Zudem gilt es nachzulesen, welche Dialekte die Entwickler des Tools vollständig im Werkzeug implementiert haben und ob Dialekt-unübliche Erweiterungen hinzukommen.
Diese Gemengelage erschwert das eindeutige Zuordnen eines Werkzeugs zu einer bestimmten Regex-Kategorie erheblich. Eine Ableitung, welche regulären Ausdrücke Sie überhaupt formulieren und mit dem Werkzeug verwenden können, gerät ohne das Studieren der Dokumentation und intensives Ausprobieren zum Glückstreffer. Selbst das Einarbeiten ins Thema mithilfe Jeffrey Friedls Meisterwerk “Mastering Regular Expressions” [3] vereinfacht die Situation nicht unbedingt.
Wie Sie sicher schon ahnen, birgt allein diese Ebene genügend Potenzial für hitzige, oft religiös geprägte Diskussionen um die Überlegenheit und Brauchbarkeit eines Dialekts oder Werkzeugs. Je nach RE-Dialekt schreiben Sie bestimmte Muster leichter oder umständlicher, das heißt mit Abkürzungen oder zusätzlichen Zeichen. Im Kasten “Regex-Dialekte” finden Sie einen kurzen Abriss zu den häufig genutzten Dialekten regulärer Ausdrücke.
Regex-Dialekte
Reguläre Ausdrücke gehen auf das Jahr 1951 und den Mathematiker Stephen Cole Kleene (1909-1994) zurück. Damals entwickelte er eine mathematisch exakte Beschreibungssprache namens Regular Events. Etliche Implementierungs- und Standardisierungsrunden später existiert heute immer noch eine Vielfalt nicht allzu einfach auseinanderzuhaltender Regex-Varianten. Die wichtigsten davon samt ausgewählter Anwendungen unter GNU/Linux zeigt die Tabelle “Ausgewählte Regex-Dialekte”.
Weitere Dialekte sowie eine ausführlichere Beschreibung samt der nicht oder zusätzlich zum Standard unterstützten Zeichenklassen sowie andere Besonderheiten finden Sie in der Regex Feature Comparison Chart [4]. Detailinformationen zu weiteren Werkzeugen mit deren Regex-Dialekt(en) liefert die Webseite Regular-expressions.info [5].
Bitte beachten Sie, dass manche Anwendungen und Programmiersprachen mehrere Dialekte unterstützen, die Sie dann mittels Schalter auswählen oder nach Auswahl der entsprechenden Funktion nutzen [6]. Typische Vertreter sind GNU Grep/Egrep (GNU BRE und GNU ERE) sowie die Programmiersprache PHP, die sowohl POSIX ERE und GNU ERE als auch PCRE anbietet.
|
Dialekt |
Abkürzung |
Beschreibung |
Anwendung |
|---|---|---|---|
|
POSIX Basic Regular Expressions |
POSIX BRE |
grundlegende Ausdrücke gemäß IEEE POSIX-Standard 1003.2 |
R |
|
POSIX Extended Regular Expressions |
POSIX ERE |
erweiterte Ausdrücke gemäß IEEE POSIX-Standard 1003.2 |
MySQL, Oracle Database 10g, PHP, PostgreSQL bis Version 7.4, R |
|
GNU Basic Regular Expressions |
GNU BRE |
POSIX BRE mit GNU-Erweiterungen |
GNU Grep, GNU Sed |
|
GNU Extended Regular Expressions |
GNU ERE |
POSIX ERE mit GNU-Erweiterungen |
GNU Egrep, GNU Awk, GNU Sed, PHP, GNU Emacs |
|
Perl Compatible Regular Expressions |
PCRE |
Regex-Dialekt von Perl |
PHP, Perl, R, Emacs mit Pcre2el-Erweiterung, Apache Webserver, Exim, Postfix, Nmap |
|
Tcl Advanced Regular Expressions |
Tcl ARE |
Regex-Kommandos von Tcl 8.2 und 8.4 |
TCL, PostgreSQL ab Version 7.4 |
|
European Computer Manufacturers Association |
ECMA 262 |
Regex-Implementierung für Webbrowser |
Javascript |
Vim-Bedienkonzepte
Bevor wir genauer auf die verwendeten Dialekte eingehen, beleuchten wir kurz, wo, wie und wozu Sie reguläre Ausdrücke in Vim und Emacs einsetzen. Hier kommen relativ konträre Bedienkonzepte ans Tageslicht. Erst besprechen wir Vim, Emacs folgt danach.
In Vim verwenden Sie reguläre Ausdrücke im Kommandomodus: Im Einfügemodus drücken Sie zunächst [Esc] und geben danach einen Schrägstrich ([Umschalt]+[ 7]) ein, gefolgt vom Suchmuster. Eine Rückwärtssuche beginnt hingegen mit einem Rückstrich ([Umschalt]+[ß]) gefolgt vom Suchmuster. Die einfache Angabe von s/Suchmuster im Kommandomodus löscht alle Vorkommen des Suchmusters im Text. Der Buchstabe g steht als Abkürzung für global und wendet eine Aktion auf jeden Suchtreffer im Text an. Das vollständige Schema dazu zeigt die Tabelle “Schema für Suchen und Ersetzen in Vim”.
|
Kommandofolge |
Bedeutung |
|---|---|
|
|
Vorwärtssuche ab aktueller Cursorposition. |
|
|
Rückwärtssuche ab aktueller Cursorposition. |
|
|
Alle Vorkommen des Suchmusters löschen. |
|
|
Suchen und Ersetzen im benannten Bereich. |
|
|
Vim-Kommando im benannten Bereich auf Zeilen anwenden, die das Suchmuster enthalten. |
Falls Sie sich fragen, ob Vim das Suchen und Ersetzen rückwärts beherrscht: Die Antwort lautet nein. Als Trennzeichen zwischen den einzelnen Komponenten der Kommandofolge fungiert üblicherweise ein Schrägstrich, es lassen sich aber auch andere Trennzeichen verwenden. Details dazu lesen Sie im Kasten “Alternative Trennzeichen unter Vim”.
Alternative Trennzeichen unter Vim
Vim benutzt als Trennzeichen zwischen den einzelnen Komponenten der Kommandofolge einen Schrägstrich. Sie können jedoch auch jedes andere Zeichen verwenden, das die Komponenten sauber und eindeutig voneinander trennt. In Listing 1 benutzen wir einen Doppelpunkt. Das erweist sich dann als hilfreich, wenn das Suchmuster oder der Ersatztext zahlreiche Schrägstriche enthält, etwa bei Pfadangaben, die Sie ansonsten jeweils vielfach escapen müssten. Im Beispiel aus dem Listing ersetzen wir die Pfadangabe /var/log/dtafile durch /var/log/datafile (erste Zeile). Mit dem Doppelpunkt als Trennzeichen lässt sich die Kommandofolge deutlich einfacher lesen (zweite Zeile).
Listing 1
Alternatives Trennzeichen
s/\/var\/log\/dtafile/\/var\/log\/datafile/g s:/var/log/dtafile:/var/log/datafile/g
Als Bereich versteht Vim den Wirkungskreis, in dem Ihre Kommandofolge Anwendung findet (siehe Tabelle “Bereichsangaben in Vim”). Spezifizieren Sie keinen Bereich, umfasst der Wirkungskreis lediglich die aktuelle Zeile.
|
Bereich |
Zeichen, Beispiel und Erklärung |
|---|---|
|
bestimmte Zeilennummer |
|
|
Bereichsangabe mit Zeilennummern |
|
|
aktuelle Zeile |
|
|
letzte Zeile |
|
|
ganzer Text |
|
|
beginne ab Markierung |
|
|
ab nächster Zeile mit neuem Suchmuster |
|
|
ab vorheriger Zeile mit neuem Suchmuster |
|
|
ab nächster Zeile mit bisherigem Suchmuster |
|
|
ab vorheriger Zeile mit bisherigem Suchtreffer |
|
|
ab nächster Zeile mit dem bisherigen Ersatztext |
|
Obige Angaben erlauben das Suchen und Ersetzen einzelner oder mehrerer Worte sowie ganzer Zeilen und Absätze im Text, die das Suchmuster enthalten. Die Bereichsangabe mit Zeilennummer ermöglicht außerdem die Ergänzung um + (nach der Zeile mit dem Suchtreffer) und - (vor der Zeile mit dem Suchtreffer). Mittels / und ? geben Sie mehrere Suchtreffer an.
Einen Treffer ersetzt Vim durch den Ersatztext. Bei einer globalen Aktion löst der Editor hingegen das von Ihnen angegebene Vim-Kommando aus (siehe Tabelle “Kommandos bei globalen Aktionen”). Wie und wann das geschieht, steuern Sie über eines oder mehrere zusätzliche Aktions-Flags (siehe Tabelle “Aktionen bei Suchtreffern”). Die einzelnen Flags kombinieren Sie bei Bedarf miteinander. Geben Sie beispielsweise beim Suchen und Ersetzen ein g als Aktions-Flag an, berücksichtigt die Software alle Treffer, ansonsten nur den ersten.
|
Kommando |
Beschreibung |
|---|---|
|
|
Suchtreffer ausgeben (“print”) |
|
|
Suchtreffer ersetzen (“search and replace”) |
|
|
Suchtreffer in die Zwischenablage kopieren (“copy”) |
|
|
Zeile mit dem Suchtreffer löschen (“delete”) |
|
|
Zeile mit dem Suchtreffer in die Zwischenablage kopieren (“yank”) |
|
|
Ergebnis schreiben (“write”) |
|
Aktions-Flag |
Beschreibung |
|---|---|
|
|
bestätige jede Ersetzung (“confirm”) |
|
|
ersetze alle Suchtreffer (“global”) |
|
|
ignoriere Groß- und Kleinschreibung (“ignore”) |
|
|
berücksichtige Groß- und Kleinschreibung (“not ignore”) |
Für mehr Klarheit sorgen an dieser Stelle einige Beispiele: Die erste Zeile von Listing 2 zeigt das Kommando, mit dem Sie ausgehend von der aktuellen Cursorposition sämtliche exakten Vorkommen der Zeichenfolge “Windows” im Text finden. Die Anweisung aus der zweiten Zeile sucht dasselbe, jedoch von der aktuellen Cursorposition zum Anfang des Texts. In der dritten Zeile sehen Sie den Befehl, um in den Zeilen 10 bis 20 alle “Windows” durch “Linux” zu ersetzen. Möchten Sie das unabhängig von Groß- und Kleinschreibung erledigen, ergänzen Sie noch ein i am Ende (Zeile 4).
Listing 2
Suchen und Ersetzen
/Windows ?Windows :10,20 s/Windows/Linux/g :10,20 s/Windows/Linux/gi :% s/Windows/Linux/g :g/Windows/norm s/Windows/Linux/g
Die Aktion lässt sich auch auf den gesamten Text anwenden: Das Kommando in Zeile 5 benutzt den Operator % für den gesamten Text und wendet darauf den Suchen-und-Ersetzen-Ausdruck an. In Zeile 6 kommt zunächst eine globale Aktion zum Einsatz, die alle Zeilen heraussucht, die den Suchbegriff “Windows” enthalten. Mit der Angabe /norm schaltet Vim in den Normalmodus [7] zurück und wendet danach auf die jeweils gefundene Zeile ein globales Suchen und Ersetzen an.
Vim kann nicht nur mit einzelnen Worten umgehen, sondern auch mit ganzen Zeilen und Absätzen. Ein Absatz beginnt beziehungsweise endet mit einer Leerzeile. Mit dem Aufruf :g/20[1-5]/norm dap suchen Sie zunächst nach allen Zeilen, in denen die Zahlen 201 bis 205 vorkommen (eine 2 gefolgt von einer 0 und einer Ziffer aus dem Bereich 1 bis 5). Mit dem Vim-Kommando dap (“delete actual paragraph”) löschen Sie den entsprechenden Absatz aus dem Text.
Geht es Ihnen darum, die Zeilen zwischen zwei Suchtreffern zu entfernen, erledigt Vim auch das. Der Befehl :/= Kapitel 1/+,/= Kapitel 2/-d löscht in einem Dokument, das reStructuredText (reST [8]) als Format verwendet, alle Zeilen zwischen den zwei Überschriften “Kapitel 1” und “Kapitel 2”.
An die Angabe des ersten Suchmusters /= Kapitel 1/ schließt sich ein + an, um jene Zeile als Grenze auszuwählen, die auf die Zeile mit dem Suchtreffer folgt. Das nachstehende Komma identifiziert Vim als Bindeglied zum zweiten Suchmuster /= Kapitel 2/. Das folgende Minuszeichen markiert als Grenze die Zeile, die sich vor der Zeile mit dem zweiten Suchtreffer befindet. Am Ende steht das Vim-Kommando d (“delete”), das die betreffenden Zeilen entfernt.
Emacs-Bedienkonzepte
Bevor Sie zu einer Reise aufbrechen, lohnt sich der Blick auf eine Landkarte – bei Emacs verhält es sich ähnlich. Zu diesem Editor gibt es eine Reihe von Referenzkarten [9] für unterschiedliche Sprachen, die häufig benutzte Tastenkombinationen von Emacs 28 enthalten.
Im Vergleich zu Vim legt Emacs ein etwas anderes Bedienkonzept zugrunde. Es kennt keine Bedienmodi und agiert stattdessen konsequent im Einfügemodus. Allerdings benutzt es komplexere Tastenkombinationen und Schlüsselworte (siehe Tabelle “Aktionen mit Regex”), um weitere Aktionen auszulösen. Sie erfordern zusätzliche Interaktion (Abbildung 1) in einem kleinen Zusatzfenster oder Minipuffer (Abbildung 2).
|
Schlüsselwort |
Beschreibung |
|---|---|
|
|
Vorwärtssuche mit Regex über [Strg]+[Alt]+[S]. Das |
|
|
Rückwärtssuche mit Regex über [Strg]+[Alt]+[R]. |
|
|
Suchen und Ersetzen ohne vorherige Rückfrage. |
|
|
Suchen und Ersetzen mit vorheriger Rückfrage über [Strg]+[Alt]+[Umschalt]+[5]. |
|
|
Zeichenketten ausrichten anhand von Regex als Begrenzern. |
|
|
Zeichenketten finden und hervorheben auf der Basis von Regex. |
|
|
Zeilen mit einem Suchtreffer anzeigen. |
|
|
Zeilen in allen Puffern mit einem Suchtreffer anzeigen. |
|
|
Suchtreffer basierend auf dem Regex zählen. |
|
|
Zeilen außer denen mit Suchtreffern löschen. |
|
|
Zeilen mit Suchtreffern löschen. |
|
|
Grep aufrufen und das Ergebnis in einem Puffer speichern. |
|
|
Benutzerfreundliche Schnittstelle zu Grep. |
|
|
Rekursives Grep verwenden. |
|
|
Dateien mit einem Dateinamen kopieren, auf die der Regex passt. |
|
|
Dateien umbenennen, auf die der Regex passt. |
|
|
Dateien anzeigen, die Regex-Treffer auf der Basis von Dired enthalten [10]. |
Die in der Tabelle “Aktionen mit Regex” genannten Tastenkombinationen funktionieren bei Ihnen möglicherweise nicht auf Anhieb, da Emacs-Pakete sie durchaus neu zuweisen. In diesem Fall versuchen Sie stattdessen die Tastenkombination [Alt]+[X] gefolgt vom ersten Buchstaben des gewünschten Befehls. Dann tippen Sie [Pfeil-oben] sowie einen weiteren Buchstaben und den Tabulator, bis Sie den gesamten gewünschten Befehl im Minipuffer (am unteren Bildschirmrand oder Fenster) sehen.
Benutzen Sie Gnome als Desktop, müssen Sie noch ein kleines Hindernis aus dem Weg räumen. Im Auslieferungszustand fängt diese Oberfläche die Tastenkombination [Strg]+[Alt]+[S] ab, um darüber zwischen unterschiedlichen Bildschirmauflösungen umzuschalten. Passen Sie die Abkürzung über die Aktivitätseinstellungen an und legen Sie eine andere Tastenfolge fest, ansonsten gelingt Ihnen keine Suche im Emacs.
Bei regulären Ausdrücken gehören das Einfügen von Text, Kopieren und Rückgängigmachen zum Alltag. Die beliebten Tastenkombinationen [Strg]+[V] (Einfügen), [Strg]+[C] (Kopieren) und [Strg]+[Z] (Rückgängigmachen) aktivieren Sie, indem Sie im Editor entweder [Alt]+[X] eingeben oder ein = in der Emacs-Konfigurationsdatei ergänzen. In der GUI der Anwendung verwenden Sie dazu das Menü Optionen.
Für etwas mehr Klarheit sollen einige Beispiele aus der Praxis sorgen. In der ersten Zeile von Listing 3 finden Sie die Tastenfolgen für die interaktive Vorwärtssuche nach den beiden Suchbegriffen “Greenwich” und “Greenwhich” (Abbildung 1), in der zweiten Zeile die dazugehörige Rückwärtssuche. Zeile 3 zeigt das Ersetzen der beiden Suchbegriffe “Windows” und “windows” durch “Linux”, Zeile 4 das Zählen der Suchtreffer für den Suchbegriff “Linux”. Der Aufruf in Zeile 5 liefert in einem Unterfenster nur jene Zeilen des Texts, die den Suchbegriff “Debian” enthalten (Abbildung 2). Um das Gegenteil zu erreichen und alle Zeilen mit dem Suchbegriff “Debian” aus dem Text zu entfernen, benutzen Sie den Befehl aus Zeile 6.
Listing 3
Interaktive Vorwärtssuche
[Strg]+[Alt]+[S]isearch-forward-regexp[Eingabe]Greenwh?ich [Strg]+[Alt]+[R]isearch-backward-regexp[Eingabe]Greenwh?ich [Esc],[X]query-replace-regexp[Eingabe][Ww]indows[Eingabe]Linux[Eingabe] [Esc],[X]how-many[Eingabe]Linux[Eingabe] [Esc],[X]occur[Eingabe]Debian[Eingabe] [Esc],[X]flush-lines[Eingabe]Debian[Eingabe]
Groß- und Kleinschreibung beachtet die Software zumindest bei der interaktiven Suche mittels query-replace-regexp in dem Moment, wo auch Großbuchstaben im Suchmuster vorkommen, ansonsten nicht. Die Suche nach “t” findet dann sowohl “t” als auch “T”, die nach “T” hingegen nur das große T.
Unterstützte Dialekte
An dieser Stelle gehen sowohl Vim [11] als auch Emacs eigene Wege. Sie benutzen beide einen Regex-Dialekt, den wir nicht eindeutig zu den in der Tabelle “Ausgewählte Regex-Dialekte” erwähnten Kategorien zuordnen können.
Bezüglich der Funktions- und Schreibweise orientiert sich Vim an Perl und GNU Grep [12]. Kurz gesagt, steht Ihnen somit in Vim eine Basismenge aus GNU BRE, GNU ERE und PCRE zur Verfügung, die die Entwickler um spezifische Erweiterungen ergänzt haben (siehe Tabelle “Wer kann was”). Wichtig zu wissen: Die Regex-Engine in Vim ist nicht vollständig PCRE-kompatibel, was Perl-Benutzer gelegentlich in die Verzweiflung treibt. Zudem besteht keine Möglichkeit, Vim mitzuteilen, ob es einen regulären Ausdruck als BRE, ERE oder PCRE interpretieren soll.
Die GNU-Implementierung von Emacs hingegen positioniert sich klar und deutlich: Sie benutzt GNU ERE mit Ausnahme der Klassen, Sortierungen und Gleichwertigkeiten (“collations and equivalences”) von POSIX [13]. Mithilfe der Erweiterung Pcre2el [14] wandeln Sie Regex-Ausdrücke zwischen PCRE, dem Emacs-Dialekt und Rx, baumartigen Ausdrücken in der Programmiersprache Lisp [15].
Noch ein Hinweis: Sie können den Zeilenanfang (^) und das Zeilenende ($) verwenden, um Zeichenketten zu finden, die sich vollständig auf einer einzigen Zeile befinden.
|
Zeichen oder Aktion |
Vim |
Emacs |
|
|---|---|---|---|
|
Angabe von Wortgrenzen |
|
|
|
|
keine Wortgrenze |
|
– |
|
|
Zeilenanfang |
|
|
|
|
Zeilenende |
|
|
|
|
Wortklassen, hier von “a” bis “z” |
|
|
|
|
jedes Zeichen zwischen den eckigen Klammern |
etwa |
– |
|
|
keines der Zeichen zwischen den eckigen Klammern |
|
– |
|
|
Gruppen |
|
|
|
|
Rückbezüge |
|
|
|
|
Mehrfachmuster (oder) |
|
|
|
|
Metazeichen |
|||
|
jedes Zeichen außer Zeilenumbruch |
|
|
|
|
Leerzeichen und Tabulator |
|
|
|
|
Leerzeichen, Tabulator, Zeilenumbruch |
|
– |
|
|
kein Leerzeichen oder Tabulator |
|
– |
|
|
Ziffer |
|
|
|
|
keine Ziffer |
|
– |
|
|
Hexadezimalwert |
|
|
|
|
alles außer Hexadezimalwert |
|
– |
|
|
Oktalwert |
|
bei |
|
|
alles außer Oktalwert |
|
– |
|
|
Zeichen für den Wortanfang (Buchstaben und Unterstrich) |
|
– |
|
|
kein Zeichen für den Wortanfang (alles außer Buchstaben und Unterstrich) |
|
– |
|
|
druckbares Zeichen |
|
|
|
|
druckbares Zeichen mit Leerzeichen |
|
– |
|
|
druckbares Zeichen außer Ziffern |
|
– |
|
|
Steuerzeichen |
|
– |
|
|
ganzes Wort |
|
|
|
|
kein ganzes Wort |
|
|
|
|
Buchstabe des Alphabets |
|
|
|
|
kein Buchstabe des Alphabets |
|
|
|
|
lateinischer Buchstabe des Alphabets |
|
– |
|
|
griechischer Buchstabe des Alphabets |
|
– |
|
|
Kleinbuchstabe |
|
|
|
|
kein Kleinbuchstabe |
|
– |
|
|
Großbuchstabe |
|
|
|
|
kein Großbuchstabe |
|
– |
|
|
Zeichen in c-Schreibweise |
|
– |
|
|
kein Zeichen in c-Schreibweise |
|
||
|
Zeilen und Spalten |
|||
|
Spalte 42 |
|
[Alt]+[G][Alt]+[G], |
– |
|
vor Spalte 42 |
|
– |
|
|
nach Spalte 42 |
|
– |
|
|
Zeile 42 |
|
– |
|
|
Cursor-Position |
|
– |
|
|
Gierige Mengenangaben (Greedy quantifiers; n,m>0) |
|||
|
0 oder mehr des vorhergehenden Zeichens, Bereichs oder Metazeichens |
|
|
|
|
alles inklusive Leerzeilen |
|
|
|
|
mindestens ein vorhergehendes (Meta-)Zeichen oder ein Bereich |
|
|
|
|
0 oder ein vorhergehendes (Meta-)Zeichen oder ein Bereich |
|
|
|
|
mindestens n und maximal m vorhergehende Zeichen, Bereiche oder Metazeichen |
|
|
|
|
exakt n vorhergehende (Meta-)Zeichen oder Bereiche |
|
|
|
|
von 0 bis maximal m vorhergehende (Meta-)Zeichen oder Bereiche |
|
|
|
|
mindestens n vorhergehende (Meta-)Zeichen oder Bereiche |
|
|
|
|
Nicht gierige Mengenangaben (Non-greedy quantifiers; n,m>0) |
|||
|
0 oder mehr vorherige (Meta-)Zeichen oder Bereiche, so wenig wie möglich |
|
– |
|
|
mindestens n und maximal m vorherige (Meta-)Zeichen oder Bereiche, so wenig wie möglich |
|
– |
|
|
mindestens n vorherige (Meta-)Zeichen oder Bereiche, so wenig wie möglich |
|
– |
|
|
von 0 bis maximal m (Meta-)Zeichen oder Bereiche, so wenig wie möglich |
|
– |
|
Aus der Praxis
Damit Sie das Einsetzen von regulären Ausdrücken in Vim und Emacs besser verstehen, haben wir mehrere, unterschiedlich komplexe Beispiele zusammengestellt. Das erste umfasst das Auffinden im Text und Prüfen auf formale Korrektheit einer deutschen und Schweizer IBAN. Im zweiten Beispiel versehen wir eine Zahl mit Tausendertrennzeichen in deutscher und britisch-englischer Schreibweise (Suchen und Ersetzen). Allerdings kann eine reine Regex-Lösung die IBAN nicht auf ihre Gültigkeit prüfen: Die IBAN enthält eine separat zu berechnende Prüfsumme, woran reguläre Ausdrücke scheitern.
Gemäß der Beschreibung der Deutschen Bundesbank [16] setzt sich die IBAN eines deutschen Bankkontos aus den beiden Buchstaben “DE”, zwei Prüfziffern, der Bankleitzahl aus acht Ziffern sowie der Kontonummer aus zehn Ziffern zusammen. Zur besseren Lesbarkeit gruppiert man im Alltag je vier Zeichen und trennt sie durch ein Leerzeichen ab, sodass Angaben der Form “DE22 1001 0050 1234 5678 90” entstehen.
Beim Auffinden einer passenden Zeichenkette müssen Sie stets davon ausgehen, dass sich Tippfehler eingeschlichen haben, und den Regex dementsprechend fehlertolerant auslegen. Die drei Ausdrücke in Listing 4 gelten für Vim und beschreiben ein einzelnes Wort, das eine Zeichenfolge aus den beiden Zeichen “D” und “E” als Groß- oder Kleinbuchstabe repräsentiert, auf die unmittelbar zwei Ziffern aus dem Bereich 0 bis 9 folgen. Die erste Zeile passt auf eine Zeichenkette mit oder ohne ein Leerzeichen als Trennzeichen zwischen zwei Ziffern, die zweite hingegen erlaubt beliebig viele Leerzeichen als Trennzeichen zwischen zwei Ziffern. Der Regex aus der letzten Zeile vereinfacht den Ausdruck: Er sucht lediglich nach den beiden Buchstaben, gefolgt von 20 Ziffern, vor denen jeweils wiederum beliebig viele Leerzeichen stehen können. Abbildung 3 zeigt das Suchergebnis in Vim, bei dem wir im Text nach passenden IBANs fahndeten.
Listing 4
Deutsche IBAN mit Vim
/\<[dD][eE][0-9]\{2\}\(\s\?[0-9]\{2\}\)\{9\}\>
/\<[dD][eE][0-9]\{2\}\(\(\s\+\)\?[0-9]\{2\}\)\{9\}\>
/\<[dD][eE]\(\(\s\+\)\?[0-9]\)\{20\}\>
Im Vergleich zu einer deutschen IBAN fällt eine Schweizer IBAN etwas kürzer aus (Abbildung 4). Sie beginnt mit den beiden Buchstaben “C” und “H” (Confoederatio Helvetica), an die sich zwei Prüfziffern anschließen. Danach folgen die Bankleitzahl (fünf Ziffern) sowie die Kontonummer (zwölf Zeichen, sowohl Ziffern als auch Groß- und Kleinbuchstaben). Listing 5 zeigt das Suchmuster, das in Emacs passende IBANs im Text aufstöbert – einmal vollständig ausgeschrieben und darunter mit der passenden Abkürzung :alnum:.
Das Muster identifiziert Zeichenketten aus “C” und “H” gefolgt von zwei Prüfziffern, keinem oder mehreren Leerzeichen, vier Gruppen aus vier Ziffern oder Buchstaben, gefolgt von keinem oder mehreren Leerzeichen sowie am Ende eine Ziffer oder ein Buchstabe. Der Regex findet beispielsweise “CH41 1000 0FSF 2023 1234 5” für ein Konto, das der Free Software Foundation (FSF) gehören könnte. Die IBAN ist in diesem Fall außerdem in Wortbegrenzer (\b) eingeschlossen. Den Sonderfall einer IBAN ausschließlich aus Ziffern – dann ist die Kontoangabe ungültig – berücksichtigt der Regex nicht.
Listing 5
Schweizer IBAN mit Emacs
\b[cC][hH][0-9]\{2\}[[:space:]]*\([0-9a-zA-Z]\{4\}[[:space:]]*\)\{4\}[[0-9a-zA-Z]]\b
\b[cC][hH][0-9]\{2\}[[:space:]]*\([:alnum:]\{4\}[[:space:]]*\)\{4\}[[:alnum:]]\b
Im zweiten Beispiel befassen wir uns mit der Vergabe von Tausendertrennzeichen. Während dazu im deutschen Sprachraum ein Punkt dient, kommt im Englischen ein Komma zum Einsatz. Listing 6 zeigt unsere Kommandofolge für den Vim, mit der wir jedoch nicht voll und ganz zufrieden sind.
Listing 6
Tausendertrennzeichen
s/\([0-9]\)\(\([0-9][0-9][0-9]\)\+$\)/\1,\2/g
Der Aufruf funktioniert zwar, aber Sie müssen das Vim-Kommando mehrfach anwenden, unabhängig davon, ob Sie das g am Ende des Suchausdrucks angeben oder nicht: Es findet stets nur eine Ersetzung pro Zeile statt. Der Versuch einer Umsetzung mittels Regex Lookahead beziehungsweise Regex Lookbehind führte nicht zum Erfolg [17]. Abbildung 5 veranschaulicht den vorletzten Schritt, bevor alle Zahlen ein Komma als Tausendertrennzeichen besitzen.
Hervorhebungen
Vim nimmt in der Vorgabe keine Hervorhebung der Suchtreffer vor, dieses Feature schalten Sie selbst ein und aus. Dazu gibt es zwei Schalter für das Kommando set namens hlsearch und nohlsearch [18].
Möchten Sie die Funktion dauerhaft einschalten, gelingt das über die Konfiguration in der .vimrc. In Listing 7 aktiviert der Befehl in der ersten Zeile die Hervorhebung der Suchtreffer, die folgenden beiden Zeilen stellen zusätzlich die gewünschte Farbkombination ein. Die zweite Zeile definiert als Hintergrundfarbe mittels ctermbg=LightYellow ein helles Gelb, die letzte Zeile mittels ctermfg=Red als Vordergrundfarbe ein Feuerwehrrot. Vim akzeptiert zur Auswahl der Vorder- und Hintergrundfarbe die Ausdrücke aus der Tabelle “Vim-Farben”. Wie diese dann tatsächlich aussehen, hängt vom Terminal ab, in dem Sie Vim benutzen.
Listing 7
Hervorhebungen und Farben
set hlsearch # Suchtreffer hervorheben hi Search ctermbg=LightYellow # Hintergrund hi Search ctermfg=Red # Vordergrund
|
Blau |
|
|
Cyan |
|
|
Gelb |
|
|
Grau |
|
|
Grün |
|
|
Magenta |
|
|
Rot |
|
|
Schwarz |
|
|
Weiß |
|
Das Pendant zu Vims hlsearch und nohlsearch sind im Emacs die beiden internen Variablen search-highlight für die normale Suche und highlight-regexp für die Suche auf der Basis regulärer Ausdrücke [19]. Setzen Sie beide auf den Wert nil, schaltet das die Hervorhebung vollständig ab, ansonsten ist sie aktiviert [20]. Im Emacs stellen Sie das über das Menü Optionen ein (Abbildung 6 zeigt Emacs 27).
Benötigen Sie die hier genannten Schritte häufiger, sind Abkürzungen ein probates Mittel, um Zeit zu sparen. In Vim helfen Ihnen dabei Makros, in Emacs heißt das Pendant Macroscript. Auf beiden Wegen speichern Sie Aktionen und Tastendrücke unter einem eigenen Namen ab und greifen bei Bedarf wieder darauf zurück. Beide Punkte hier noch vorzustellen, sprengt allerdings den Rahmen dieses Beitrags. In einem Folgeartikel gehen wir darauf ausführlicher ein.
Fazit
Das Wissen um reguläre Ausdrücke vereinfacht das Umsetzen komplexer Vorgänge rund um das Suchen und Ersetzen in Textdateien. Sowohl Vim als auch Emacs unterstützen das Konzept in umfangreicher Form, gehen dabei jedoch in der Formulierung und der Ausführung unterschiedliche Wege.
Möchten Sie Regex lernen und ausprobieren (PCRE), hilft Ihnen die Webseite Regexr.com [21] weiter. Diese Spielwiese möchten wir Ihnen nicht vorenthalten. (csi/jlu)
Danksagung
Die Autoren bedanken sich bei Axel Beckert und Veit Schiele für deren Anregungen beim Erstellen des Artikels. Gerold bedankt sich ausdrücklich bei Ben Forta [22] – mit dessen Buch “Teach Yourself Regular Expressions in 10 Minutes” [23] tauchte er in die Welt der regulären Ausdrücke ein.
Über die Autoren
Frank Hofmann arbeitet zumeist von unterwegs, bevorzugt in Berlin, Genf und Kapstadt, als Entwickler, Trainer und Autor. Er gehört zu den Verfassern des Debian-Paketmanagement-Buchs. Der gebürtige Kanadier Gerold Rupprecht wohnt seit 30 Jahren in Genf und hat sich auf Finanzsoftware sowie die Evaluierung und die Optimierung von IT-bezogenen Prozessabläufen spezialisiert. Seit der Jahrtausendwende unterstützt er das GNUstep-Projekt.
Infos
-
Reguläre Ausdrücke: Frank Hofmann, “Schnipseljagd”, LU 09/2011, S. 84: https://www.linux-community.de/24091
-
Regex-Generatoren: Frank Hofmann, “Muster finden”, LU 08/2021, S. 82: https://www.linux-community.de/46467
-
“Mastering Regular Expressions”: http://regex.info/book.html
-
“Regular Expression Engine Comparison Chart”: https://gist.github.com/CMCDragonkai/6c933f4a7d713ef712145c5eb94a1816
-
“Specialized Tools and Utilities for Working with Regular Expressions”: https://www.regular-expressions.info/tools.html
-
“Comparing regular expressions in Perl, Python, and Emacs”: https://www.johndcook.com/blog/regex-perl-python-emacs/
-
Modi in Vim: https://www.warp.dev/terminus/vim-modes
-
reStructuredText: https://docutils.sourceforge.io/rst.html
-
Emacs-Referenzkarte: https://www.gnu.org/software/emacs/refcards/
-
Emacs-Handbuch, Find and Dired: https://www.gnu.org/software/emacs/manual/html_node/emacs/Dired-and-Find.html
-
“The Vim Regular Expression Dialect”: https://medium.com/usevim/the-vim-regular-expression-dialect-7fd0b07d2a6a
-
Vimregex: http://vimregex.com/
-
Regex im Emacs-Wiki: https://www.emacswiki.org/emacs/RegularExpression
-
“Pcre2el: Convert between PCRE, Emacs and rx regexp syntax”: https://github.com/joddie/pcre2el
-
S-Expression: https://en.wikipedia.org/wiki/S-expression
-
IBAN-Regeln: https://www.bundesbank.de/de/aufgaben/unbarer-zahlungsverkehr/serviceangebot/iban-regeln/iban-regeln-603042
-
“Regex Lookahead and Lookbehind”: https://vim.fandom.com/wiki/Regex_lookahead_and_lookbehind
-
“Highlight all search pattern matches”: https://vim.fandom.com/wiki/Highlight_all_search_pattern_matches
-
“Highlighting by Word, Line and Regexp”: https://www.masteringemacs.org/article/highlighting-by-word-line-regexp
-
“Tailoring Search to Your Needs”: https://www.gnu.org/software/emacs/manual/html_node/emacs/Search-Customizations.html
-
Regexr: https://regexr.com
-
“Learning Regular Expressions”: https://forta.com/books/0134757068/
-
“Teach Yourself Regular Expressions in 10 Minutes” (ISBN *0672325667): https://www.oreilly.com/library/view/sams-teach-yourself/0672325667/











