Regular Expression: Unterschied zwischen den Versionen
Zeile 67: | Zeile 67: | ||
== Suchmuster == | == Suchmuster == | ||
[[Regular Expression/Suchmuster]] | |||
== Listen == | == Listen == |
Version vom 14. Oktober 2024, 11:34 Uhr
Regular Expression (Regulärer Ausdruck) - Sprache zur Beschreibung von Zeichenketten
Beschreibung
Ein regulärer Ausdruck (regular expression,RegExp oder Regular expression) ist eine Zeichenkette, die der Beschreibung von Zeichenketten mithilfe bestimmter syntaktischer Regeln dient.
- Reguläre Ausdrücke finden vorwiegend in der Softwareentwicklung Verwendung; für fast alle Programmiersprachen existieren Implementierungen.
- Eine Regular Expression (im folgenden mit RE abgekürzt) ist so etwas wie ein Suchmuster, das dazu dient, komplizierte Suchanfragen mit wenigen Zeichen zu formulieren.
- Die Syntax ist standardisiert und wird von verschiedenen Programmen verstanden, z. B. sed, egrep, expr, perl. Das interpretierende Programm versucht, aus einer größeren Zeichenmenge (i.A. einer Zeile) eine Teilmenge zu finden, die zu der RE "passt".
- Oft gibt es mehrere Teilmengen, die passen. In diesem Fall wird die größte Teilmenge als Ergebnis verwendet.
- Pattern Matching
- Reguläre Ausdrücke können als Filterkriterien in der Textsuche verwendet werden, indem der Text mit dem Muster des regulären Ausdrucks abgeglichen wird.
- So ist es beispielsweise möglich, alle Wörter aus einer Wortliste herauszusuchen, die mit S beginnen und auf D enden – ohne die dazwischenliegenden Buchstaben und wahlweise deren Anzahl explizit vorgeben zu müssen.
Zeichenketten finden
- Eine häufige Anwendung regulärer Ausdrücke besteht darin, spezielle Zeichenketten in einer Menge von Zeichenketten zu finden.
- Die im Folgenden angegebene Beschreibung ist eine (oft benutzte) Konvention, um Konzepte wie Zeichenklasse, Quantifizierung, Verknüpfung und Zusammenfassen konkret zu realisieren.
- Metazeichen
- Hierbei wird ein regulärer Ausdruck aus den Zeichen des zugrunde liegenden Alphabets in Kombination mit den Metazeichen [ ] ( ) { } | ? + - * ^ $ \ . (teilweise kontextabhängig) gebildet.
- Die Meta-Eigenschaft eines Zeichens kann durch ein vorangestelltes Backslash-Zeichen aufgehoben werden.
- Alle übrigen Zeichen des Alphabets stehen für sich selbst.
- Textersetzungen
- Ein weiteres Beispiel für den Einsatz als Filter ist die Möglichkeit, komplizierte Textersetzungen durchzuführen.
- Neben den aufgeführten analytischen Aufgaben können reguläre Ausdrücke auch verwendet werden, um Mengen von Wörtern zu erzeugen, ohne jedes Wort einzeln angeben zu müssen.
- So lässt sich beispielsweise ein Ausdruck angeben, der bei einer gegebenen (Maximal-)Zeichenanzahl alle denkbaren Zeichenkombinationen („Wörter“) erzeugt, die mit S beginnen und mit D enden. Auf diese Weise können etwa systematisch E-Mail-Adressen (vor allem der Teil vor dem @) für den Spam-Versand generiert werden.
Erweiterungen
- Die meisten heutigen Implementierungen unterstützen Erweiterungen wie zum Beispiel Rückwärtsreferenzen (backreferences). Hierbei handelt es sich nicht mehr um reguläre Ausdrücke im Sinne der theoretischen Informatik, denn die so erweiterten Ausdrücke beschreiben nicht mehr notwendigerweise Sprachen vom Typ 3 der Chomsky-Hierarchie.
- Die folgenden Syntaxbeschreibungen beziehen sich auf die Syntax der gängigen Implementierungen mit Erweiterungen, sie entsprechen also nur teilweise der obigen Definition aus der theoretischen Informatik.
Anwendung regulärer Ausdrücke
Ken Thompson nutzte diese Notation in den 1960ern, um qed (eine Vorgängerversion des Unix-Editors ed) zu bauen und später das Werkzeug grep zu schreiben.
Seither implementieren viele Programme und Bibliotheken von Programmiersprachen Funktionen, um reguläre Ausdrücke zum Suchen und Ersetzen von Zeichenketten zu nutzen.
Beispiele für Regular expressionp-Implementierungen
Programme | Bibliotheken der Programmiersprachen | |
* sed | * Perl | * PHP |
Auch die Textverarbeitung und die Tabellenkalkulation des Office-Paketes OpenOffice.org bieten die Möglichkeit, mit regulären Ausdrücken im Text zu suchen.
Implementierungen
- Basic Regular Expressions (BRE)
- „grundlegende“ reguläre Ausdrücke
- Extended Regular Expressions (ERE)
- „erweiterte“ reguläre Ausdrücke
- Perl Compatible Regular Expressions] (PCRE)
- In Programmiersprachen haben sich überwiegend die Perl Compatible Regular Expressions (PCRE) durchgesetzt, die sich an der Umsetzung in Perl orientieren.
Einige Programme, etwa der Texteditor Vim, ermöglichen, zwischen verschiedenen Syntaxen zu wechseln.
siehe POSIX.2
Suchmuster
Listen
- Listen (bracket expressions)
Erwartet man an einer Stelle innerhalb des Regulären Ausdrucks nicht ein ganz bestimmtes Zeichen, sondern nur eines aus einer spezifischen Liste, so kann man dies durch eine sogenannte bracket expression ausdrücken.
Die Liste der Zeichen, aus der das zu findende Zeichen stammen soll, wird dazu einfach in eckigen Klammern "[]" angegeben. Um beispielsweise alle Buchstaben "a", egal ob groß oder klein, zu finden, verwendet man folgenden regulären Ausdruck: "[Aa]"
Möchte man alle Zeichen finden, die nicht in der Liste stehen, die Liste also negieren, so muss das erste Zeichen in der Liste ein Caret "^" sein. Ein regulärer Ausdruck der Form "[^Aa]" passt also auf alle Zeichen, die weder ein großes noch ein kleines "a" sind.
- Beispiel
[Aa]lpha* findet alle Textstücke "Alpha" und "alpha".
Range Expression
Um die Listen der bracket extensions kompakt darstellen zu können, werden range expressions verwendet. Ein range expression wird durch zwei Zeichen, die durch einen Bindestrich miteinander verbunden sind, dargestellt:
[a-d]
Ein solcher Ausdruck passt auf alle Zeichen, die in der Sortierung des Zeichensatzes zwischen die beiden Zeichen fallen.
Auswahl einzelner Zeichen
Zeichenauswahl ([ und ])
- Der Ausdruck in eckigen Klammern steht dann für genau ein Zeichen aus dieser Auswahl.
- Innerhalb dieser Zeichenklassendefinitionen haben einige Symbole andere Bedeutungen als im normalen Kontext.
Zeichenklassen (Character Classes)
Eine Character Class definiert einen Zeichenvorrat. Sie besteht aus einer Menge von ein oder mehreren Zeichen und wird innerhalb von eckigen Klammern angegeben. Die Reihenfolge der Zeichen ist beliebig.
- Beispiele
[ae]* Zeichenvorrat besteht nur aus "a" und "e" [aeiou]* alle Vokale in Kleinbuchstaben [aeiouAEIOU]* in Klein- und Großbuchstaben [a-fh-k]* Buchstaben a-f und h-k [^a]* alle Zeichen außer "a" [^abc]* alle Zeichen außer "a", "b" oder "c" (Reihenfolge gleichgültig!)
Kontextabhängige Symbole
Teilweise ist die Bedeutung eines Symbols vom Kontext abhängig, in dem es innerhalb der Klammern auftritt.
^ | * Beispielsweise bedeutet ein Zirkumflex „^“ am Anfang einer Zeichenklassendefinition, dass die Zeichenklasse negiert/invertiert wird (im Sinne der Komplementbildung).
|
- | Ebenfalls kontextabhängig ist die Bedeutung des Bindestrich-Zeichens (-). Zudem unterscheiden sich hier die Regular expressionp-Engines (zum Beispiel POSIX und PCRE) in einigen Punkten voneinander. * Steht - zwischen zwei Zeichen in der Klassendefinition, zum Beispiel „[a-g]“, so ist es als Beschreibung eines Zeichenintervalls oder Zeichenbereichs bezüglich der ASCII-Tabelle zu verstehen.
|
Beispiel
„[^ ]$“ * Zeichenkette muss aus mind. einem Zeichen bestehen und
das letzte Zeichen darf kein Leerzeichen sein
Sortierung
Leider hängt diese Sortierung von der verwendeten locale-Einstellung ab. In der Standard C locale würde obiges Muster "[a-d]" einem regulären Ausdruck von "[abcd]" entsprechen, während er bei vielen anderen locales einem Ausdruck "[aBbCcDd]" entsprechen würde.
Um die C locale für die Zeichensortierung zu erzwingen, kann man der Variablen LC_CTYPE den Wert C zuweisen:
LC_CTYPE=C befehl* gilt nur für diesen Befehl LC_CTYPE=C grep -E [a-d] Datei export LC_CTYPE=C* gilt für alle nachfolgenden Befehle
Die meisten Zeichen mit besonderer Bedeutung verlieren diese Bedeutung innerhalb eines bracket expressions. Um ein Zeichen "]" in die Liste aufzunehmen, muss es an der ersten Stelle in der Liste stehen.
Um das Caret "^" in die Liste aufzunehmen, kann es irgendwo in der Liste stehen, nur nicht an der ersten Stelle. Um den Bindestrich "-" in die Liste einzufügen, muss es an letzter Stelle stehen.
Zeichenklassen
- Vordefinierten Zeichenklassen
In vielen neueren Implementationen können innerhalb der eckigen Klammern nach POSIX auch Klassen (vordefinierte Listen) angegeben werden, die selbst wiederum eckige Klammern enthalten.
POSIX | Non-standard | Perl/Tcl | Vim | ASCII | Description |
[:alnum:] | [A-Za-z0-9] | Alphanumeric characters | |||
[:word:] | \w | \w | [A-Za-z0-9_] | Alphanumeric characters plus "_" | |
\W | \W | [^A-Za-z0-9_] | Non-word characters | ||
[:alpha:] | \a | [A-Za-z] | Alphabetic characters | ||
[:blank:] | \s | [ \t] | Space and tab | ||
\b | \< \> | (?<=\W)(?=\w)|(?<=\w)(?=\W) | Word boundaries | ||
[:cntrl:] | [\x00-\x1F\x7F] | Control characters | |||
[:digit:] | \d | \d | [0-9] | Digits | |
\D | \D | [^0-9] | Non-digits | ||
[:graph:] | [\x21-\x7E] | Visible characters | |||
[:lower:] | \l | [a-z] | Lowercase letters | ||
[:print:] | \p | [\x20-\x7E] | Visible characters and the space character | ||
[:punct:] | [][!"#$%&'()*+,./:;<=>?@\^_`{| class="wikitable sortable"}~-] | Punctuation characters | |||
[:space:] | \s | \_s | [ \t\r\n\v\f] | Whitespace characters | |
\S | [^ \t\r\n\v\f] | Non-whitespace characters | |||
[:upper:] | \u | [A-Z] | Uppercase letters | ||
[:xdigit:] | \x | [A-Fa-f0-9] | Hexadecimal digits |
POSIX Zeichenklassen können nur innerhalb von Klammer-Ausdrücken genutzt werden.
- Vordefinierten Zeichenklassen müssen in eckige Klammern
falsch
grep -E '[:alnum:]' Datei
- findet z. B. 'a', da es eines der Zeichen ':alnum:' ist, aber nicht 'b' oder '1'
- (die vordefinierte Liste wird nicht als solche interpretiert!)
richtig
grep -E '[[:alnum:]]' Datei
- findet sowohl 'a', als auch 'b' oder '1', da die vordefinierte Liste nun als "Buchstabe oder Zahl" interpretiert wird
grep -E '[[:alnum:] ]' Datei
- findet zusätzlich zu Buchstaben und Zahlen auch Leerzeichen
grep -E '[0-9a-zA-Z]' Datei
- entspricht alnum:
Zeichenklassen, hierarchisch sortiert
[:cntrl:] — Steuerzeichen. Im ASCII sind das die Zeichen 00 bis 1F und 7F (DEL).
[:print:] — Druckbare Zeichen: [:alnum:], [:punct:] und Leerzeichen [:blank:] — Leerzeichen oder Tabulator [:space:] — Whitespace: Horizontaler und vertikaler Tabulator, Zeilen- und Seitenvorschub, Wagenrücklauf und Leerzeichen [:graph:] — Graphische Zeichen: [:alnum:] oder [:punct:] [:punct:] — Satzzeichen wie: ! " # $ % & ' ( ) * + , - . / : ; < = > ? @ [ \ ] ^ _ ` { | } ~ [:alnum:] — Alphanumerische Zeichen: [:alpha:] oder [:digit:] [:xdigit:] — Hexadezimale Ziffern: 0 bis 9, A bis F, a bis f. [:digit:] — Die Ziffern 0 bis 9 [:alpha:] — Buchstaben: [:lower:] oder [:upper:] [:lower:] — Kleinbuchstaben: nicht notwendigerweise nur von a bis z [:upper:] — Großbuchstaben: nicht notwendigerweise nur von A bis Z |
Anmerkung
Was Buchstaben sind, ist im Allgemeinen locale-abhängig, also abhängig von der eingestellten Region und Sprache. |
|
Anmerkungen: |
Beispiel
Die Buchstaben "y" und "i" sollen durch "xx" ersetzt werden.
echo -e "Mayer\nMaier\nMeyer\nMeier" | sed 's/[yi]/xx/'
Beachten Sie, dass beim Suchen und Ersetzen immer alle Zeilen komplett ausgegeben werden, unabhängig davon ob Ersetzungen durchgeführt wurden oder nicht. Daher lassen sich mehrere Suchen und Ersetzen Anweisungen gut aneinanderreihen.
"i" und "y" sollen durch "ii" ersetzt werden, sodann "a" und "e" durch "oo"
$ echo -e "Mayer\nMaier\nMeyer\nMeier" | sed -e 's/[iy]/ii/g' -e 's/[ae]/oo/g' Mooiioor
Vordefinierte Zeichenklassen
Es gibt vordefinierte Zeichenklassen, die allerdings nicht von allen Implementierungen unterstützt werden, da sie lediglich Kurzformen sind und auch durch eine Zeichenauswahl beschrieben werden können.
Wichtige Zeichenklassen sind:
\d | digit | eine Ziffer [0-9] |
\D | no digit | ein Zeichen, das keine Ziffer ist, also [^\d] |
\w | wordcharacter | ein Buchstabe, eine Ziffer oder der Unterstrich, also [a-zA-Z_0-9] (und evtl. weitere Buchstaben, z. B. Umlaute) |
\W | no wordcharacter | ein Zeichen, das weder Buchstabe noch Zahl noch Unterstrich ist, also [^\w] |
\s | whitespace | meistens das Leerzeichen und die Klasse der Steuerzeichen \f, \n, \r, \t und \v |
\S | no whitespace | ein Zeichen, das kein Whitespace ist [^\s] |
\b | leere Zeichenkette am Wortanfang oder am Wortende | |
\B | leere Zeichenkette, die nicht den Anfang oder das Ende eines Wortes bildet | |
\< | leere Zeichenkette am Wortanfang | |
\> | leere Zeichenkette am Wortende | |
\n | newline | ein Zeilenumbruch im Unix-Format |
\r | return | ein Zeilenumbruch im Mac-Format |
\r\n | ein Zeilenumbruch im Windows-Format |
Weitere Zeichen
^ | steht für den Zeilenanfang (nicht zu verwechseln mit „^“ bei der Zeichenauswahl mittels „[“ und „]“). |
$ | kann je nach Kontext für das Zeilen- oder Stringende stehen, wobei bei manchen Implementierungen noch ein „\n“ folgen darf. Das tatsächliche Ende wird von \z gematcht. |
\ | hebt gegebenenfalls die Metabedeutung des nächsten Zeichens auf. Beispielsweise lässt der Ausdruck „(A\*)+“ die Zeichenketten „A*“, „A*A*“, usw. zu. Auf diese Weise lässt sich auch ein Punkt „.“ mit „\.“ suchen, während nach „\“ mit „\\“ gesucht wird. |
Weitere Beispiele
[egh]
- eines der Zeichen „e“, „g“ oder „h“
[0-6]
- eine Ziffer von „0“ bis „6“ (Bindestriche sind Indikator für einen Bereich)
[A-Za-z0-9]
- ein beliebiger lateinischer Buchstabe oder eine beliebige Ziffer
[^a]
- ein beliebiges Zeichen außer „a“ („^“ am Anfang einer Zeichenklasse negiert selbige)
[-A-Z], [A-Z-] bzw. [A-Z\-a-z], allerdings nicht gemäß POSIX)
- Auswahl enthält auch den Bindestrich „-“, wenn er das erste oder das letzte Zeichen in der Aufzählung einer Zeichenklasse ist bei PCRE, wenn seine Metafunktion innerhalb einer Auswahl durch ein vorangestelltes „\“-Zeichen aufgehoben wird
\<[Aa]+n+[ae]+\>
- findet alle Wörter, die ungefähr wie Anne oder Anna aussehen, nur mit beliebig vielen "A", "n" und "e" (sofern sie jeweils mindestens ein mal vorkommen). AAnnneeea würde zum Beispiel auch passen.
[Ss]up(er|ra)
- findet alle Wörter, die ein Super, super, Supra oder supra enthalten.
^digit:
- findet alle Zeilen, die mit einer Ziffer beginnen.
Quantoren
- Wiederholungsfaktoren (Quantoren)
Quantoren (engl. quantifier, auch Quantifizierer) erlauben es, den vorherigen Ausdruck in verschiedener Vielfachheit in der Zeichenkette zuzulassen.
? | Der voranstehende Ausdruck ist optional, er kann einmal vorkommen, muss es aber nicht, d. h. der Ausdruck kommt null- oder einmal vor. (Dies entspricht {0,1}) |
+ | Der voranstehende Ausdruck muss mindestens einmal vorkommen, darf aber auch mehrfach vorkommen. (Dies entspricht {1,}) |
* | Der voranstehende Ausdruck darf beliebig oft (auch keinmal) vorkommen. (Dies entspricht {0,}) |
>n} | Der voranstehende Ausdruck muss exakt n-mal vorkommen. |
>min,} | Der voranstehende Ausdruck muss mindestens min-mal vorkommen. |
>max} | Der voranstehende Ausdruck muss mindestens min-mal und darf maximal max-mal vorkommen. |
>max} | Der voranstehende Ausdruck darf maximal max-mal vorkommen. |
Funktionsweise
Die Quantoren beziehen sich dabei auf den vorhergehenden regulären Ausdruck, jedoch nicht zwangsläufig auf die durch ihn gefundene Übereinstimmung. * So wird zwar zum Beispiel durch a+ ein „a“ oder auch „aaaa“ vertreten,
- jedoch entspricht [0-9]+ nicht nur sich wiederholenden gleichen Ziffern, sondern auch Folgen gemischter Ziffern, beispielsweise „072345“.
Beispiele
„[ab]+“ * entspricht „a“, „b“, „aa“, „bbaab“ etc.
„[0-9]{2,5}“ * entspricht zwei, drei, vier oder fünf Ziffern in Folgez. B. „42“ oder „54072“, jedoch nicht den Zeichenfolgen „0“, „1.1“ oder „a1a1“.
Gieriges Verhalten von Quantoren
Quantoren sind standardmäßig „gierig“ (engl. greedy) implementiert.
Soll eine Zeichenkette nur aus dem gesuchten Muster bestehen (und es nicht nur enthalten), so muss in den meisten Implementierungen explizit definiert werden, dass das Muster vom Anfang (\A oder ^) bis zum Ende der Zeichenkette (\Z, \z oder $) reichen soll.
- Andernfalls erkennt zum Beispiel [0-9]{2,5} auch bei der Zeichenkette „1234507“ die Teilzeichenkette „12345“.
- Aus dem gleichen Grund würde beispielsweise a* immer einen Treffer ergeben, da jede Zeichenfolge – selbst das leere Wort „“ – mindestens 0-mal das Zeichen „a“ enthält.
- Das heißt, ein regulärer Ausdruck wird zur größtmöglichen Übereinstimmung aufgelöst.
Genügsame Quantoren
Da dieses Verhalten jedoch nicht immer so gewollt ist, lassen sich bei vielen neueren Implementierungen Quantoren als „genügsam“ oder „zurückhaltend“ (engl. non-greedy, reluctant) deklarieren.
- Zum Beispiel wird in Perl hierfür dem Quantor ein Fragezeichen ? nachgestellt.
- Die Implementierung von genügsamen Quantoren ist vergleichsweise aufwändig (erfordert Backtracking), weshalb nicht alle Implementierungen diese unterstützen.
Beispiel (Perl-Syntax)
- Angenommen, es wird der reguläre Ausdruck A.*B auf die Zeichenfolge „ABCDEB“ angewandt, so würde er sie komplett als „ABCDEB“ finden.
- Mit Hilfe des „non-greedy“-Quantors „*?“ matcht der nun modifizierte Ausdruck – also A.*?B – nur die Zeichenkette „AB“, bricht also die Suche nach dem ersten gefundenen „B“ ab.
- Ein gleichwertiger regulärer Ausdruck für Interpreter, die diesen Quantor nicht unterstützen, wäre A[^B]*B.
Die Zeichen ^ und $ matchen im multiline-Modus (wenn der m-Modifier gesetzt wird) auch Zeilenanfänge und -enden.
Possessives Verhalten
Eine Variante des oben beschriebenen gierigen Verhaltens ist das possessive Matching.
- Da hierbei jedoch das Backtracking verhindert wird, werden einmal übereinstimmende Zeichen nicht wieder freigegeben.
- Aufgrund dessen finden sich in der Literatur auch die synonymen Bezeichnungen atomic grouping, independent subexpression oder non-backtracking subpattern.
- Die Syntax für diese Konstrukte variiert bei den verschiedenen Programmiersprachen.
Ursprünglich wurden solche Teilausdrücke (Subpattern) in Perl durch (?>Ausdruck) formuliert.
Daneben existieren seit Perl 5.10 die äquivalenten, in Java bereits üblichen possessiven Quantoren ++, *+, ?+ und {min,max}+.
Angenommen es wird auf die Zeichenfolge „ABCDEB“ der reguläre Ausdruck A.*+B angewandt, so würde er keine Übereinstimmung finden.
- Bei der Abarbeitung des regulären Ausdrucks würde der Teil .*+ bis zum Ende der Zeichenkette übereinstimmen.
- Um jedoch den gesamten Ausdruck zu matchen, müsste ein Zeichen (hier also das „B“) wieder freigegeben werden.
- Der possessive Quantor verbietet dies aufgrund des unterdrückten Backtrackings, weshalb keine erfolgreiche Übereinstimmung gefunden werden kann.
Gruppierungen und Referenzen
Gruppierungen
Ausdrücke lassen sich mit runden Klammern ( und ) zusammenfassen:
„(abc)+“ erlaubt ein „abc“, „abcabc“, „abcabcabc“ etc.
Rückreferenzen
Einige Implementierungen speichern die gefundenen Übereinstimmungen von Gruppierungen ab und ermöglichen deren Wiederverwendung im regulären Ausdruck oder bei der Textersetzung.
Diese werden Rückwärtsreferenzen (engl. back references) genannt.
Häufig wird dazu die Schreibweise \n oder $n verwendet, wobei n die Übereinstimmung der n-ten Gruppierung entspricht.
Eine Sonderstellung stellt dabei n=0 dar, das meist für die Übereinstimmung des gesamten regulären Ausdruck steht.
Beispiel * Ein Suchen und Ersetzen mit AA(.*?)BB als regulären Suchausdruck und \1 als Ersetzung ersetzt alle Zeichenketten, die von AA und BB eingeschlossen sind, durch den zwischen AA und BB enthaltenen Text.
- D.h. AA und BB und der Text dazwischen werden ersetzt durch den Text, der ursprünglich zwischen AA und BB stand, also fehlen AA und BB im Ergebnis.
Geklammerte Ausdrücke referenzieren
Eine Teilzeichenkette, die auf einen geklammerten Teilausdruck gepasst hat, lässt sich durch "\n" referenzieren. Dabei steht "n" für eine einzelne Ziffer, die den n-ten geklammerten Teilausdruck auswählt.
Bezugnahme auf die Ergebnismenge
Bei den bisherigen Anweisungen wurde der gesamte Zeileninhalt ausgegeben. Es gibt jedoch die Möglichkeit, direkt auf die effektive Ergebnismenge oder einen Teil daraus Bezug zu nehmen.
Die hierfür erforderliche s-Anweisung führt kein Suchen und Ersetzen durch, sondern durchsucht den Datenstrom anhand der RE und bildet aufgrund des Ausdrucks in () nochmals eine Teilmenge, die ausgegeben werden kann.
BeispielTESTEN!! Aus der folgenden Zeile soll nur das Element "blau" ausgegeben werden.
echo "-rot-blau-gelb" | sed 's/.*\(blau\).*/\1/g'
Die gesamte RE lautet: /.*blau.*/
Es soll jedoch nur der Teil der Ergebnismenge ausgegeben werden, der "blau" enthält. Folglich ist "blau" in runde Klammern zu setzen.
/.*\(blau\).*/ echo "-rot-blau-gelb" | sed 's/.*\(blau\).*/\1/g'
- s"Suchen und Ersetzen", wobei kein "Ersetzen" durchgeführt wird
- .*Beginn der RE: beliebiges Zeichen 0-n mal
- \(blau\)"blau" soll, falls es sich aus der Ergebnismenge extrahieren läßt, ausgegeben werden
- .*Ende der RE: beliebiges Zeichen 0-n mal
- \1die Ergebnismenge der 1. geklammerten RE wird ausgegeben
- bei mehreren REs, wird jeder RE eine Zahl zugeordnet: \1 = 1.RE \2 = 2.RE usw.
Praktische Anwendung von Rückreferenzen
Umschreiben einer URL
Image
Gruppierungen ohne Rückreferenz
engl. non-capturing Die Syntax lautet in den meisten Implementierungen (?:…).
Regular expressionp-Dokumentationen weisen darauf hin, dass die Erzeugung von Rückwärtsreferenzen stets vermieden werden soll, wenn kein späterer Zugriff auf sie erfolge.
Denn die Erzeugung der Referenzen kostet Ausführungszeit und belegt Platz zur Speicherung der gefundenen Übereinstimmung.
Zudem lassen die Implementationen nur eine begrenzte Anzahl an Rückwärtsreferenzen zu (häufig nur maximal 9).
Beispiel
\d+(?:-\d+)*
- Findet Folgen von durch Bindestriche getrennte Zahlenfolgen, ohne dabei die letzte durch einen Bindestrich getrennte Zahlenfolge als Rückreferenz zu erhalten.
Suchen & Ersetzen
Beim reinen s-Befehl werden immer alle Zeilen ausgegeben, unabhängig davon, ob Ersetzungen durchgeführt wurden oder nicht. Dies lässt sich ändern, indem man ihn mit dem p-Befehl kombiniert. Die Abläufe sind wie folgt:
p-Befehl
echo "dies wird nicht ausgegeben" | sed -n '/.*diiss.*/p'
- gibt es eine Ergebnismenge, die zur RE "passt"?
- wenn ja, gibt die ganze Zeile aus.
s-Befehl ohne p-Befehl
echo "dies wird ausgegeben" | sed 's/wird/wird immer/'
- gibt es eine Ergebnismenge, die zur RE "passt"?
- wenn ja, welches ist die effektive Ergebnismenge?
- ersetze diese durch den Replace-String
- gib die ganze Zeile aus (egal, ob geändert oder nicht)
s-Befehl mit p-Befehl
echo -e "xxx\nnächste Zeile" | sed -n 's/xxx/Ausgabe/p'
- Die Kombination von s- und p-Befehl bewirkt, dass
- nur die geänderten Zeilen ausgegeben werden.
- Die Option -n darf nicht vergessen werden.
Im Allgemeinen ist es sinnvoll, den g-Spezifizierer ("global") zu verwenden, der direkt vor oder hinter dem p-Befehl steht:
echo -e "xxx--xxx\nnächste Zeile" | sed -n 's/xxx/Ausgabe/pg'
- alle "xxx" werden ersetzt
Ersatzmuster
Bei einigen Tools (ex, sed und ed) werden zwei Muster angegeben: Ein Suchmuster (links) und ein Ersatzmuster (rechts). Nur die folgenden Zeichen sind in einem Ersatzmuster gültig:
ex | sed | Ed | ||
\ | X | X | X | Sonderbedeutung des nächsten Zeichens aufhebe |
\n | X | X | X | Verwendet das in \( \) gespeicherte Muster erneut |
& | X | X | Verwendet das vorherige Suchmuster erneut | |
~ | X | Verwendet das vorherige Ersatzmuster erneut | ||
\u | X | Ändert das erste Zeichen des Ersatzmusters auf Großschreibung | ||
\U | X | Ändert alle Zeichen des Ersatzmusters auf Großschreibung | ||
\l | X | Ändert das erste Zeichen des Ersatzmusters auf Kleinschreibung | ||
\L | X | Ändert alle Zeichen des Ersatzmusters auf Kleinschreibung | ||
\E | X | Hebt das vorangegangene \U oder \L auf | ||
\e | X | Hebt das vorangegangene \u oder \l auf |
Verknüpfungen
- Verknüpfung regulärer Ausdrücken
Mehrere reguläre Ausdrücke können durch Aneinanderfügen zusammengeführt werden. Ein solcher Ausdruck findet dann alle Zeichenketten, die aneinander gehängt zu dem jeweiligen Ausdruck passen.
Beispiel
"[Aa]lpha"
Es besteht aus den einzelnen Bausteinen
- "[Aa]"
- "l"
- "p"
- "h"
- "a"
Verknüpfung durch "oder"
Durch den Operator "|" lassen sich reguläre Ausdrücke mit einem "oder" verknüpfen.
Der daraus entstehende Ausdruck findet Zeichenketten, die entweder auf den einen oder den anderen Ausdruck passen.
Beispiel
"[Aa]lpha|[Bb]ravo"
- findet alle Textstücke "Alpha", "alpha", "Bravo" und "bravo"
- grep -E oder egrep
echo "--rot--gelb--" | sed 's/\(gelb\|rot\)/x/g' echo "--rot--gelb--" | sed 's/gelb\|rot/x/g'
- die runden Klammern und das oder-Zeichen "|" müssen escaped werden
- die runden Klammern können weggelassen werden
Alternativen
Man kann alternative Ausdrücke mit dem „|“-Symbol zulassen.
„ABC|abc“ bedeutet „ABC“ oder „abc“, aber z. B. nicht „Abc“.
Beispiele
a|b* * "a", "b", "bb", "bbb", …
(a|b)*
- beliebig viele „a“ und „b“, einschließlich einer leeren Zeichenkette
- „“, „a“, „b“, „aa“, „ab“, „ba“, „bb“, „aaa“, …
ab*(c|ε)
- ε = leer
- Zeichenketten beginnend mit „a“
- kein- oder mehrmals „b“
- optional a "c": {"a", "ac", "ab", "abc", "abb", "abbc", ...}
(0|(1(01*0)*1))*
- set of binary numbers that are multiples of 3: { ε, "0", "00", "11", "000", "011", "110", "0000", "0011", "0110", "1001", "1100", "1111", "00000", ... }
Rangfolge
- Rangfolge der Regeln
Ähnlich wie bei mathematischen Ausdrücken (Punkt- vor Strichrechnung) unterliegen die Verknüpfungsoperatoren einer Rangfolge:
- Wiederholungen kommen vor Verkettungen
- Verkettungen vor "oder"
- Diese Regeln lassen sich durch Klammern überschreiben