Community-Wiki

Achtung: Fandom stellt ab dem 31.12.2023 bis auf Weiteres den Support für die deutsche Sprache ein. Nach diesem Datum müssen alle Anfragen im englischen Community Central oder über das Kontaktformular gestellt werden.

MEHR ERFAHREN

Community-Wiki
Community-Wiki
Advertisement
Community-Wiki

Reguläre Ausdrücke, oder kurz „Regex“, sind Zeichenketten, die zum Durchsuchen von Textdateien verwendet werden können. In einem Wiki verwendet man sie normalerweise, um den Quelltext von Wikiseiten zu durchsuchen und Änderungen an einer Seite vorzunehmen. Dies wird am häufigsten mit dem Werkzeug AutoWikiBrowser, oder AWB, gemacht. Diese Seite befasst sich mit regulären Ausdrücken im Zusammenhang mit AWB, aber bedenke, dass verschiedene Regex-Engines, wie z. B. Notepad++ und SublimeText, einige Dinge anders behandeln können. Wenn du Module schreibst, unterscheiden sich die String-Muster von Lua erheblich von Regex. Diese Seite wird nicht zu sehr ins Detail gehen, sodass alle Hauptkonzepte unabhängig von dem Programm, das du verwendest, anwendbar sein sollten, aber bedenke, dass einige Dinge anderswo eine etwas andere Syntax haben könnten.

Ressourcen zum Üben und Testen von Regex[]

Beispiele[]

Wie benutzt man diesen Leitfaden?[]

Dieser Leitfaden ist für Leute geschrieben, die sich beim Lesen von technischen Texten unsicher fühlen. Wenn es dir nichts ausmacht, technische Dokumentationen zu lesen, bietet die Seite regular-expressions.info eine viel vollständigere und präzisere Erklärung von allem, was du über Regex wissen willst - allerdings zu dem Preis, dass sie von Anfang an sehr technisch ist, und es könnte dich überwältigen, bis du zumindest ein bisschen Erfahrung hast. Du kannst auch die Verweise auf reguläre Ausdrücke im AWB-Leitfaden von Wikipedia als „Spickzettel“ verwenden.

Das Ziel dieser Seite ist es, dich auf die Verwendung von regular-expressions.info als Ressource vorzubereiten, nicht dir alles beizubringen, was du über Regex wissen musst.

AWB-spezifische reguläre Ausdrücke[]

Eine kurze Anmerkung, bevor wir starten...

Was bedeuten „mehrzeilig“ und „einzeilig“ in AWB? Du verstehst das vielleicht noch nicht, aber dies ist eine FAQ über Regex in AWB und deshalb sollte sie am Anfang stehen. Es steht dir frei, diesen Abschnitt vorerst zu überspringen und später wiederzukommen.

Wenn du AutoWikiBrowser verwendest, gibt es einige Optionen, die mit regulären Ausdrücken verbunden sind, „mehrzeilig“ und „einzeilig“. Auf den ersten Blick mag es so aussehen, als ob „mehrzeilig“ bedeutet, dass du mehrere Zeilen eingibst, und „einzeilig“ bedeutet, dass du nur eine Zeile eingibst, aber tatsächlich haben diese beiden Begriffe sehr spezifische Bedeutungen. Wenn du auf „Testen“ klickst und den Mauszeiger über die beiden Begriffe im AWB Regex Tester bewegst, erscheint ein Hinweis, falls du nicht mehr weißt, was was ist.

  • Mehrzeilig – Standardmäßig passen die Zeichen ^ und $ auf den Anfang und das Ende der gesamten Wikiseite. Wenn du dies anklickst, ändern sie ihre Bedeutung und passen auf den Anfang und das Ende jeder Zeile – oder, mit anderen Worten, es behandelt deinen Wikitext als hätte er mehrere Zeilen, auf die du passen willst.
  • Singleline – Standardmäßig passt das Zeichen . auf alles außer dem Zeilenumbruchzeichen. Das Zeichen für den Zeilenwechsel wird durch \n angegeben. Wenn du dieses Kästchen anklickst, ändert . seine Bedeutung, sodass es auf neue Zeilen passt. Mit anderen Worten: Deine Wikiseite wird so behandelt, als ob sie eine einzige Zeile wäre, damit sie auf .* oder einen anderen Quantifizierer passt.

Untersuchung des Konzepts einer Erfassungsgruppe[]

Stell dir das folgende Szenario vor:

Du bist fünf Jahre alt und spielst Minesweeper auf dem Computer deiner Eltern. Nach etwa 10 Minuten wird dir langweilig und du beschließt, dir die offenen Fenster anzusehen. Eines davon ist eine Notepad++-Datei mit einer Einkaufsliste! Du weißt, dass Mama immer Einkaufslisten schreibt und Papa dann die Einkäufe erledigt, und er kauft immer das, was auf der Liste steht. Eine brillante Idee beginnt, sich zu formen. Wie wäre es, wenn du jeden einzelnen Punkt auf der Einkaufsliste mit „Süßigkeiten“ überschreiben würdest – stell dir vor, wie viele Süßigkeiten du dann essen könntest!

Im Moment sieht die Einkaufsliste wie folgt aus:

GS - Mehl
GS - Milchpulver
GS - Zucker
GS - Kürbis
GS - Allzweckgewürz
OSS - Toner
AS - Überraschung

Du bewegst den Mauszeiger zur ersten Zeile und änderst „Mehl“ in „Süßigkeiten“. Aber du bist erst fünf Jahre alt – das Tippen ist so schwer! „Oh je“, sagst du. „Es muss doch einen besseren Weg geben, all diese Ersetzungen vorzunehmen!“ Du kennst die Funktion „Suchen-Ersetzen“, aber du siehst nicht, wie das hier MÖGLICHERWEISE helfen könnte. In deiner Verzweiflung wendest du dich an deinen Roboterfreund. „Roboterfreund, kannst du helfen?“, sagst du. Aber dein Roboterfreund ist ein Aufziehspielzeug aus Plastik und sagt gar nichts.

„Ah, ich kenne das Problem!“, denkst du. „Roboterfreund braucht bestimmte Anweisungen, weil er ein Roboter ist!“ Du denkst eine Sekunde lang nach. „Roboterfreund, ändere jeden Gegenstand so, dass er Süßigkeiten sagt!“ Roboterfreund tut immer noch nichts. Wieder fragst du dich, warum. „Hmm“, sagst du. „Vielleicht liegt es daran, dass der Roboterfreund nicht weiß, was ein Gegenstand ist!“

Das ist eine ziemlich gute Vermutung! (Es hat natürlich nichts damit zu tun, dass du mit einem Plastikspielzeug sprichst.) In der Lebensmittelliste ist jeder Artikel eine Abkürzung für einen Ladentyp und dann für das, was man in diesem Laden kaufen kann. GS steht für Grocery Store, OSS für Office Supply Store... und was ist AS? Na ja, was auch immer, wahrscheinlich gibt es dort auch Süßigkeiten.

„Roboterfreund“, sagst du. „Ersetze in jeder Zeile dieser Textdatei den gesamten Inhalt nach dem Bindestrich durch das Wort Süßigkeiten.“ Wow, das ist wirklich genau! Leider ist Roboterfreund immer noch ein Plastikspielzeug und tut nichts.

„Okay“, sagst du. „Ich werde das googeln!“ Du gehst also zu Google und suchst: „Wie ändere ich alles auf der Einkaufsliste meiner Eltern in Süßigkeiten?“ Das erste Ergebnis lautet: „Lerne reguläre Ausdrücke, um Süßigkeiten zu bekommen“.

„Das sieht vielversprechend aus“, sagst du, öffnest den Link und fängst an zu lesen. Das Erste, was du tun musst, ist, das Fenster zum Suchen und Ersetzen in Notepad++ zu öffnen. „Wow, wie praktisch, dass meine Eltern so einen schönen Texteditor für ihre Einkaufslisten benutzen“, denkst du. Du drückst Strg+H, um das Dialogfeld Ersetzen direkt aufzurufen, und klickst auf die Option „Regulärer Ausdruck“.

Das Erste, was du tun musst, sagt die Website, ist herauszufinden, was du finden willst. „Aber das ist doch offensichtlich, das ist doch das Ding nach dem Bindestrich“, denkst du dir. Aber dann erinnerst du dich an Roboterfreund und seine genaue Anweisungsanforderung. „Ohhh“, denkst du. „Suchen und Ersetzen ist wie ein virtueller Roboterfreund!“ Erfreut darüber, dass du jetzt ZWEI Roboterfreunde hast, überlegst du, wie du genauer beschreiben kannst, wo du die Änderung vornehmen willst.

„Also, jede Zeile beginnt mit einem Ort. Ich möchte, dass dies vom Suchen bis zum Ersetzen gleich bleibt. Dann kommt ein Bindestrich, und den möchte ich auch beibehalten. Und das Leerzeichen nach dem Bindestrich soll auch erhalten bleiben. Aber alles, was danach kommt, muss ich komplett löschen! Da muss Süßes draufstehen!“

Nun gut, das ist eine gute Erklärung für einen Menschen, aber nicht für einen Roboterfreund. Wie kann man genau sagen: „Behalte alles bis einschließlich des Leerzeichens nach dem Bindestrich bei und ändere den Rest der Zeile in die Zeichenfolge Süßigkeiten?“

Du liest mehr auf der Website. „Verwende Erfassungsgruppen, um Teile deiner Zeichenkette gleich zu halten“ heißt es in der nächsten Überschrift. Wenn du einen Teil deines Suchbegriffs in () einschließt, wird er erfasst! Ah, perfekt!

Beim normalen Suchen und Ersetzen kannst du etwas beibehalten, indem du es einfach in den Ersetzungsteil eintippst. Wenn du „Katze“ in „Katze“ ändern wolltest, würdest du einfach zweimal „Katze“ schreiben und es würde alle Ersetzungen vornehmen, aber nichts würde sich ändern. Die Schwierigkeit besteht hier nicht darin, dass man etwas von „Finden“ bis „Ersetzen“ beibehalten muss, sondern darin, dass man nicht weiß, was man beibehält.

Ah, dafür gibt es eine Lösung! Wenn du irgendwie „Alles bis einschließlich des Leerzeichens nach dem -“ formal darstellen kannst, kannst du mit regulären Ausdrücken die Zeichen, auf die deine formale Definition zutrifft, ERFASSEN und dann in der Ersetzungszeichenfolge mit dem Code „$1“ aufrufen! Und danach willst du nur noch das Wort „Süßigkeiten“ ausgeben... das sollte nicht allzu schwer sein!

Also mal sehen... die Suchzeichenkette wird etwa so aussehen:

([Formale Art, alles durch Bindestrich+Leerzeichen anzugeben])[Formale Art, alles andere anzugeben]

(In der obigen Darstellung sind die Klammern () bedeutungsvolle Zeichen, die eigentlich Teil der Syntax regulärer Ausdrücke sind. Die Klammern [] dienen nur der besseren Lesbarkeit und haben keine Bedeutung).

Und dann sieht die Ersetzungszeichenfolge genau so aus: $1Süßigkeiten

Es ist zwar für dieses Beispiel nicht relevant, aber du wirst feststellen, dass du bei Bedarf MEHR ALS EINE ERSATZGRUPPE einfügen könntest, auf die du dann mit $1, $2 usw. in der Ersetzungszeichenfolge zugreifen könntest. Du könntest sogar die Reihenfolge deiner Captures ändern, indem du auf $2 vor $1 zugreifst! Wow, das ist ja super spannend.

Aber wie kann man dieses Problem lösen? Sieh dir das Beispiel auf der Website an. Dort steht, dass .* auf ALLES passt. Na toll! Du denkst. Ich schreibe (.*).* und ersetze es durch „$1Süßigkeiten“!

Aber wenn du das versuchst, bekommst du Folgendes:

GS - MehlSüßigkeiten
GS - MilchpulverSüßigkeiten
GS - ZuckerSüßigkeiten
GS - KürbisSüßigkeiten
GS - AllzweckgewürtzSüßigkeiten
OSS - TonerSüßigkeiten
AS - ÜberraschungSüßigkeiten

Huch, nicht das! Du erkennst deinen Fehler schnell. Roboterfreund macht immer genau das, was du ihm sagst ... und du hast ihm nie gesagt, dass er am Strich anhalten soll! Du versuchst es ein anderes Mal:

Finde: (.*) - .*
Ersetze: $1Süßigkeiten

GSSüßigkeiten
GSSüßigkeiten
GSSüßigkeiten
GSSüßigkeiten
GSSüßigkeiten
OSSSüßigkeiten
ASSüßigkeiten

Oh, oh, immer noch nicht ganz... Wenden wir an, was wir über zwei Erfassungsgruppen gelernt haben!

Finde: (.*)( - ).*
Ersetze: $1$2Süßigkeiten

GS - Süßigkeiten
GS - Süßigkeiten
GS - Süßigkeiten
GS - Süßigkeiten
GS - Süßigkeiten
OSS - Süßigkeiten
AS - Süßigkeiten

Ahhh, perfekt! Aber denk mal eine Sekunde lang nach. Brauchst du wirklich zwei Erfassungsgruppen? Was wäre, wenn du stattdessen dies versuchen würdest:

Finde: (.*) - .*
Ersetze: $1 - Süßigkeiten

GS - Süßigkeiten
GS - Süßigkeiten
GS - Süßigkeiten
GS - Süßigkeiten
GS - Süßigkeiten
OSS - Süßigkeiten
AS - Süßigkeiten

Juhu, das funktioniert auch! Zufrieden und erschöpft speicherst du die neue Einkaufsliste und bringst Roboterfreund ins Bett.

Am nächsten Tag sagt Mami: „Es tut mir so leid, wir wollten heute einen Kürbiskuchen backen, aber dann hat Papa stattdessen einen Haufen Halloween-Süßigkeiten gekauft! Wir werden also eine Menge Süßigkeiten haben, die wir an die Süßes-oder-Saures-Kinder verteilen können, aber wir können keinen Kuchen backen.“ Oh nein, was hast du getan? Du hast deine Roboterfreund-Kräfte für das Böse eingesetzt und jetzt bekommst du keinen Kuchen? „Aber es gibt etwas, das das wieder gut macht“, fährt Mami fort. „Darf ich dir dein neues Kätzchen vorstellen, das wir adoptiert haben und das Papa aus dem Tierheim abgeholt hat! Wir nennen sie Süßigkeiten, weil das so auf der Einkaufsliste stand!“

Ohh, dafür stand also AS! Du vergisst den Kuchen komplett und spielst mit deinem neuen Kätzchen. Das Ende.

Was haben wir also bis jetzt gelernt?

  • Reguläre Ausdrücke sind eine Möglichkeit, relativ komplizierte Anweisungen zum Suchen und Ersetzen präzise auszudrücken.
  • .* passt auf alles
  • Wenn ein Teil eines regulären Ausdrucks in Klammern eingeschlossen wird, wird er für die Ersetzungszeichenfolge "erfasst".
  • Erfassungsgruppen werden nacheinander mit den Nummern 1, 2, 3, 4 usw. versehen.
  • Die Ersetzungszeichenfolge kann auf Erfassungsgruppen mit $1, $2 usw. verweisen. Die Reihenfolge wird ausschließlich durch die Suchzeichenfolge bestimmt, und die Ersetzungszeichenfolge kann auf Erfassungsgruppen in beliebiger Reihenfolge verweisen.

Zeichenklassen, Escaping und Quantifizierer[]

Angenommen, du führst ein Tagebuch darüber, wie viele Kätzchen du jeden Tag siehst:

Sonntag - 5 Kätchen gesehen
Montag - 3 Kätchen gesehen
Dienstag - 7 Kätchen gesehen
Mittwoch - 2 Kätchen gesehen

Du beschließt eines Tages, dass du anfangen willst, in vollständigen Sätzen zu schreiben. Du würdest also lieber schreiben: „Am Sonntag habe ich 5 Kätzchen gesehen.“ Du willst also sowohl ein Wort (den Wochentag) als auch eine Zahl (die Anzahl der Kätzchen, die du an diesem Tag gesehen hast) „einfangen“ und in deine Ersetzungszeichenfolge einfügen. In unserem ersten Beispiel haben wir einfach .* verwendet, um den gesamten Textabschnitt auszuwählen. Aber lass uns genauer beschreiben, was wir erfassen wollen!

Eine Zeichenklasse ist eine präzise Methode, um dem Programm mitzuteilen, welche Art von Zeichen in einer bestimmten Gruppe von Zeichen enthalten sein dürfen. Zum Beispiel kann „eine Ziffer“ als \d geschrieben werden. „Ein Buchstabe“ kann als \w geschrieben werden. „Ein Zeichen“ kann als . geschrieben werden - ja, viele Zeichen haben in der Syntax regulärer Ausdrücke eine besondere Bedeutung! Glücklicherweise weiß das Programm, dass du vielleicht einen tatsächlichen Punkt im Suchtext brauchst, und es gibt dir die Möglichkeit, das zu tun - wenn du \. eingibst, dann wird der Punkt durch den Backslash „umgangen“.

Hinweis zur Internationalisierung - \w passt nicht zu allen Unicode-Zeichen, sei vorsichtig, wenn du dies mit Nicht-ASCII-Buchstaben verwendest!

Beachte, dass ich „eine Ziffer“ und „einen Buchstaben“ gesagt habe - aber in der Erklärung, was wir tun wollen, heißt es „eine Zahl“ und „ein Wort“! Alle Wochentage sind eine Menge Buchstaben lang. Und was ist, wenn ich an einem einzigen Tag 10 Kätzchen gesehen habe? Dann ist die Zahl 2 Ziffern lang!

Nun, auch dafür gibt es eine Lösung. Wenn du \d+ schreibst, entspricht das „einer oder mehreren Ziffern“ - oder mit anderen Worten, einer Zahl. Wenn du \w+ schreibst, bedeutet das „ein oder mehrere Buchstaben“. Und wenn wir .+ schreiben, bedeutet das „ein oder mehrere Zeichen beliebigen Typs“.

Hinweis zu den Zahlentypen: \d+ ist nicht schlau genug, um zu wissen, dass manchmal Kommas oder Punkte in der Mitte von Zahlen stehen. Es passt also nur auf positive ganze Zahlen ohne Platzhalter!

(\w+) - (\d+) Kätzchen gesehen wird zu:
Am $1, sah ich $2 Kätzchen

Beachte, dass wir in der Zeichenfolge „Ersetzen“ den Punkt NICHT auslassen müssen. Das liegt daran, dass unsere Ersetzungszeichenfolge zu 100 % genau definiert sein muss. Dem Programm zu sagen: „Ersetze das Wort 'Sonntag' durch eine beliebige Menge von Zeichen“ ergibt überhaupt keinen Sinn, während „Finde eine beliebige Menge von Zeichen zwischen dem Wort 'Kätzchen' und 'niedlich'“ durchaus Sinn ergibt.

Was ist, wenn die Daten unvollständig sein könnten? Vielleicht habe ich am Donnerstag vergessen, die Anzahl der Kätzchen aufzuschreiben, die ich gesehen habe, sodass meine Zeichenfolge nur „Donnerstag - Kätzchen gesehen lautet“. Ich möchte dies in den Satz „Am Donnerstag habe ich Kätzchen gesehen umwandeln“, und zwar in derselben Aktion, in der ich auch alles andere ersetze. Aber \d+ stimmt mit 1 oder mehr Ziffern überein, und... hier gibt es 0 Ziffern. Es stellt sich heraus, dass es auch dafür einen Weg gibt!

(\w+) - (\d* *)Kätzchen gesehen wird zu:
Am $1, sah ich $2Kätzchen.

Achtung! Wir haben auch das Leerzeichen zusammen mit dem \d* eingefügt, denn wenn die Ziffer nicht da ist, wird auch das folgende Leerzeichen nicht da sein!

Hier haben wir unser + in ein * umgewandelt. Das *-Zeichen ist ähnlich wie das +-Zeichen, außer dass es mit „0“ oder mehr Zeichen übereinstimmen kann. Mit dieser Ersetzung wird also sowohl „Donnerstag - Kätzchen gesehen“ als auch „Mittwoch - 10 Kätzchen gesehen“ korrekt umgewandelt.

Die Zeichen * und + werden Quantifizierer genannt, weil sie die Anzahl der übereinstimmenden Zeichen quantifizieren können. Es gibt noch eine weitere Sache, die man über Quantifizierer wissen sollte.

Nehmen wir an, unser Ausgangstext sähe stattdessen so aus:

Sonntag - 2 Kätzchen und ein paar Kaninchen und 3 Welpen gesehen
Montag - ein paar Lamas und ein paar Kätzchen und 2 Elefanten gesehen
Dienstag - 5 Bären und ein Einhorn gesehen

Wir wollen dies wie folgt umformulieren:

Am Sonntag habe ich 2 Kätzchen gesehen. Außerdem habe ich einen Haufen Kaninchen und 3 Welpen gesehen.
Am Montag habe ich ein paar Lamas gesehen. Außerdem habe ich ein paar Kätzchen und 2 Elefanten gesehen.
Am Dienstag habe ich 5 Bären gesehen. Außerdem habe ich ein Einhorn gesehen.

Früher war die Anzahl der Tiere, die wir gesehen haben, immer eine Ansammlung von Ziffern, oder \d+. Aber jetzt haben wir auch ein paar englische Ausdrücke darunter gemischt! Wir können also nicht nur \d verwenden. Glücklicherweise haben wir auch die Zeichenklasse . entdeckt. Also benutzen wir die:

(\w+) - (.+) gesehen und (.*) (https://regex101.com/r/Fe033j/1/) wird zu:
Am $1, Sah ich $2. Außerdem sah ich $3.

Doch halt! Es gibt ein Problem! Das ist das Ergebnis, das wir tatsächlich erhalten:

Am Sonntag, sah ich 2 Kätzchen und ein paar Häschen. Außerdem sah ich 3 Welpen.
Am Montag, sah ich ein paar Lamas und einige Kätzchen. Außerdem sah ich 2 Elefanten.
Am Dienstag, sah ich 5 Bären. Außerdem sah ich ein Einhorn.

Siehst du das Problem? Anstatt 1$ vom - zum ersten und zu gehen, sind wir den ganzen Weg zum zweiten gegangen! Oh nein, das ist überhaupt nicht das, was wir wollen. Die Quantifizierer + und * sind „gierig“ - sie nehmen so viele Zeichen wie möglich für sich selbst, bevor sie dich zum nächsten Teil deiner „Finden“-Zeichenkette weitergehen lassen. Wir wollen das Gegenteil – so „wenige“ wie möglich nehmen.

Das Gegenteil von „gierig“ könnte „großzügig“ sein, aber wir haben es ja mit Lastern zu tun. Also nennen wir die Version, die so wenig Zeichen wie möglich benötigt, „faul“. Es gibt also „gierige“ Quantoren, die so viel wie möglich nehmen, und „faule“ Quantoren, die so wenig wie möglich nehmen. Die Notation für faule Quantoren lautet wie folgt:

  • +? entspricht 1 oder mehr Zeichen, so wenig wie möglich
  • *? entspricht 0 oder mehr Zeichen, so wenig wie möglich

Lass uns also stattdessen das Folgende abgleichen:
(\w+) - (.+?) und (.*) gesehen wird zu: Am $1, sah ich $2. Außerdem sah ich $3.

Und jetzt bekommen wir das gewünschte Ergebnis!

Zur Wiederholung:

  • „Zeichenklassen“ sind Gruppen von Zeichentypen, zum Beispiel „Ziffern“ oder „Buchstaben“. Es gibt eine Menge von Zeichenklassen, die wir hier nicht behandelt haben.
  • Mit „Quantifizierern“ kannst du mehr als ein Zeichen auf einmal finden. Wir haben 4 Quantifizierer kennengelernt - +, *, +?, und *?.
  • Einige Sonderzeichen, wie z. B. ., müssen mit einem \ umgangen werden, wenn man nach ihnen in einer Zeichenkette suchen will, da sie sonst eine besondere Bedeutung haben.

Nochmals: Denke daran, dass wir nicht annähernd jeden Aspekt von Regex in diesen Themen erschöpfend behandeln werden. Schau dir die Ressourcen an, die am Anfang des Abschnitts verlinkt sind, um mehr Informationen zu erhalten!

„Alternation“, auch bekannt als „Oder“[]

Angenommen, du hattest eine besonders aufregende Woche, in der du an manchen Tagen Kätzchen, an manchen Tagen Häschen und an manchen Tagen Welpen gesehen hast! Da du einen guten Geschmack für niedliche Babytiere hast, findest du Kätzchen und Häschen viel niedlicher als Welpen. Deine Daten sehen wie folgt aus:

Sonntag - 5 Kätzchen gesehen
Montag - 3 Kaninchen gesehen
Dienstag - 7 Kaninchen gesehen
Mittwoch - 2 Welpen gesehen

Du willst die Informationen über Kätzchen und Hasen entfernen und beide Wörter durch „süße Tiere“ ersetzen. Ohne Regex könnten Sie dies mit 2 separaten Suchvorgängen erreichen: zuerst Kätzchensüße Tiere und dann Häschensüße Tiere. Aber mit Regex brauchen wir nur eine einzige Suche!

Kätzchen|Häschen wird zu:
süße Tiere

Das Zeichen | wird als „Alternator“ bezeichnet, was eine wirklich ausgefallene Art ist, „oder“ zu sagen. Damit kannst du den Text auf der linken Seite ODER den Text auf der rechten Seite vergleichen.

Lass uns unser Ziel leicht abändern. Anstatt einfach nur „Kätzchen“ und „Häschen“ durch „süße Tiere“ zu ersetzen, wollen wir etwas mehr Abwechslung hineinbringen! Versuchen wir, das so umzuformulieren, dass aus Sonntag - 5 Kätzchen gesehenSonntag - Hurra, 5 süße Tiere! wird. Aber da Welpen nicht so niedlich sind, lassen wir das einfach weg. Wir können ganz einfach die gerade gelernte „Alternation“ verwenden:

- (\d) Kätzchen gesehen|- (\d) Häschen gesehen wird zu...

Moment, wie können wir das ersetzen, um das zu bekommen, was wir wollen? Denk daran, dass die Capture-Gruppen von links nach rechts nummeriert sind. Unsere Anzahl der Tiere könnte also entweder $1 oder $2 sein, und wir wissen nicht, welche. Aber eigentlich wird eines davon leer sein, also könnten wir sie einfach so nebeneinander stellen:

- Hurra, $1$2 süße Tiere!

Du kannst dieses Beispiel selbst ausprobieren, wenn du sehen willst, dass es funktioniert und weiter machen willst.

Wenn die Sache mit $1$2 und einem leeren Wort etwas verwirrend und kompliziert erscheint, dann liegt das daran, dass es so ist. Denn was wir wirklich wollen, ist, dass ein „oder“ nur auf das letzte Wort der Zeile angewendet wird und der erste Teil in Ruhe gelassen wird. Wie können wir das erreichen?

Nicht-erfassende Gruppen[]

Wow, was für ein Cliffhanger im letzten Abschnitt. Lass uns zunächst das Beispiel von dort zu Ende bringen. Es hat sich herausgestellt, dass man, wenn man einen Alternator (daran denken, das ist eine schicke Art, „oder“ zu sagen, und es wird so geschrieben: |) in eine Capture-Gruppe einfügt, das „oder“ nur auf einen Teil der Übereinstimmung anwenden kann! Probieren wir es aus:

- (\d) (Kätzchen|Häschen) gesehen wird zu:
- Hurra, $1 süße Tiere gesehen!

SUPER! Klammern können zwei Dinge tun: eine Operation bündeln und AUCH den Inhalt „einfangen“, um ihn in der Ausgabe zu verwenden! Aber wollen wir immer beide Dinge tun? Eigentlich verwenden wir den Inhalt dieser zweiten Erfassungsgruppe nicht, es gibt keine $2 im Ersatztext. Erfinden wir also eine Syntax, die besagt: „Ich möchte den gruppierenden Teil dieser Capture-Gruppe, aber ich möchte sie nicht wirklich erfassen.“ Mit anderen Worten, wir wollen eine Gruppe, die nicht erfasst, oder... eine nicht-erfassende Gruppe!

- (\d) (?:Kätzchen|Häschen) gesehen wird zu:
- Hurra, $1 süße Tiere gesehen!

Siehst du das ?: am Anfang der Gruppe? Das bedeutet: „Ich brauche eine Gruppe, aber ich will nicht, dass sie erfasst wird.“ Das kann ziemlich nützlich sein, insbesondere wenn du viel alternieren willst, und auch, wenn du jemals eine Regex bearbeitest und eine Gruppe hinzufügen musst, aber nicht deinen Ersetzungsbegriff ändern willst, nur weil du mehr Gruppierungen hinzufügst.

Wenn du die ?:-Syntax verwirrend findest, ist das kein Problem – nicht-erfassende Gruppen fügen der Regex keine neue Funktionalität hinzu, die du ohne sie nicht hättest, sie machen es nur einfacher, mit deinen erfassenden Gruppen zu arbeiten.

Behauptungen mit Null-Breite[]

Hinweis - dies ist NICHT dasselbe Thema wie „Null-Längen-Übereinstimmungen“ auf regular-expressions.info!

Wie „Alternator“ ist dies ein unheimlich anmutender Ausdruck, der eine einfache Bedeutung hat. Doch bevor wir den Begriff definieren, sollten wir ein paar Dinge über reguläre Ausdrücke wissen. Wenn du die Zeichenfolge caaaaat finden willst, könntest du ca+t schreiben. Oder du könntest caa*t schreiben (das ist äquivalent) (nimm dir einen Moment Zeit, um herauszufinden, warum diese Regex dasselbe sind, falls es dir nicht klar ist). Das c stimmt mit dem c überein, dann stimmt das a+ oder aa* mit allen a's überein, und dann stimmt das t mit dem t überein. Das heißt, wenn du das c gefunden hast, wars das auch schon. Das c ist erledigt. In der Regex ist keine weitere c-Übereinstimmung mehr möglich.

(Das ist übrigens kein Zufall. Wenn du in ein umfangreiches Labyrinth eintauchen willst, sieh dir reguläre Sprachen oder deterministische endliche Automaten auf Wikipedia an.)

Was wäre also, wenn wir einige Dinge mehr als einmal finden wollten? Sagen wir zum Beispiel, wir wollen das Wort „cat“ finden, aber NICHT das Wort „catastrophe“ oder „cats“. Kein Problem, einfach nach „cat“ suchen, richtig? Falsch! Was wäre, wenn die Zeichenkette „cat“ oder „cat“ oder sogar „cat“ enthielte? Uhhhhhh ok, vielleicht ist das nicht so gut. Was wir also tun wollen, ist, wie zu sagen, nach Katze zu suchen und dann nach einem Nicht-Buchstaben-Zeichen zu suchen. (Wenn du die zusätzlichen Informationen über Zeichenklassen gelesen hast, weißt du, wie man das macht - wenn nicht, schau es dir an!) Was aber, wenn „cat“ das allerletzte Zeichen im Dokument ist?

Hier kommen dann die „Null-Breite-Behauptung“ ins Spiel. Dieser Ausdruck bedeutet „etwas, von dem wir verlangen, dass es wahr ist, ohne dass es unsere Suche in irgendeiner Weise vorantreibt“. Oder anders ausgedrückt: „eine Möglichkeit, eine Eigenschaft der Zeichenkette zu überprüfen, die eigentlich keine Zeichen in der Zeichenkette enthält.“

Die einfachsten Ausdrücke mit Null-Breite sind ^, was „Anfang der Zeile oder Datei“ bedeutet, und $, was „Ende der Zeile oder Datei“ bedeutet. Die Wahl zwischen Zeile und Datei hängt von den Einstellungen ab, die du gewählt hast, siehe AWB-spezifische reguläre Ausdrücke. Der im cat-Beispiel verwendete Ausdruck ist cat\b. \b bedeutet „Grenze“ und setzt voraus, dass ein Wort an dieser Stelle beginnt oder endet.

Lookaround[]

Eine umfassende Behandlung dieses Themas findest du unter regular-expressions.info.

Eine besondere Art von Null-Breiten-Assertion wird „Lookaround“ genannt. Dieser Abschnitt ist hier enthalten, weil die Leute oft danach fragen, aber die Wahrheit ist, dass dies unnötig kompliziert ist und fast jede Regex-Implementierung einen einfacheren Weg hat, um das Gleiche zu erreichen. Mit „Lookaround“ kannst du deiner Regex eine Null-Breiten-Assertion hinzufügen, die hinter oder vor einer Bedingung prüft, ob diese wahr oder falsch ist, und wenn deine Spezifikation verletzt wird, hebt sie die Fähigkeit der Regex auf, zu passen. Klingt verwirrend? Nun, es handelt sich um eine komplizierte Syntax und ein kompliziertes Konzept, das durch die Verwendung der Registerkarte „If...“ in der erweiterten Suche von AWB ersetzt werden kann, die extrem einfach ist und Sinn ergibt. Aber wenn dir die Idee gefällt, dass du nicht auf eine Schaltfläche klicken musst, um die Registerkarte „if“ zu verwenden, und dafür eine komplizierte Syntax lernst, die noch schwieriger zu verwenden ist, dann lies weiter!

Nehmen wir an, du möchtest Kätzchen sind süß durch Ja, Kätzchen sind süß ersetzen. Aber, oh nein!!! Jemand hat deinen schönen Satz so verunstaltet, dass er manchmal Kätzchen sind süß (nicht!!!) heißt. Wer würde so etwas tun? Wir wollen BESTIMMT nicht schreiben Ja, Kätzchen sind süß (nicht!!!), das wäre ja schrecklich! Was wir also tun wollen, ist, Stellen zu finden, an denen steht, dass Kätzchen süß sind<UND DANN HIER NICHT (nicht!!!) SAGEN>. Nun wissen wir nicht, was nach dem Satz an schönen Stellen kommt – es könnte ein Punkt sein, es könnte ein ! sein, es könnte ein Zeilenende sein, oder etwas ganz anderes. Wir können also keine Garantie dafür geben, was da ist, sondern nur dafür, was nicht da ist. Klingt nach einer Aufgabe für eine Behauptung mit Null-Breite!

Das, was wir jetzt verwenden werden, heißt NEGATIVE LOOKAHEAD. Negativ, weil es NICHT hier sein soll, und Lookahead, weil wir nach ....vorne schauen. Die anderen Typen sind POSITIVE LOOKAHEAD, NEGATIVE LOOKBEHIND, und POSITIVE LOOKBEHIND. All diese 4 Arten ähneln sich sowohl im Konzept als auch in der Verwendung, weshalb sie unter dem Oberbegriff „Lookaround“ zusammengefasst werden.

Schauen wir uns also zunächst die Syntax an. Wie bereits erwähnt, solltest du regular-expressions.info verwenden, um alle Informationen zu erhalten, wir gehen hier nur auf den negativen Lookahead ein.

Kätzchen sind süß(?! \(nicht!!!\))

Den ersten Teil verstehen wir vollkommen, Kätzchen sind süß, nun ja, Kätzchen sind süß. Aber was ist mit dem zweiten Teil? Zunächst einmal müssen wir feststellen, dass \( und \) nur die wörtlichen ( und ) Zeichen sind, sie müssen umgangen werden. Und nicht!!! ist nur das wörtliche Zeichen nicht!!!. Bleibt noch der Rahmen, (?!MANCHMAL GEHTS HIER). Nun, wie wir bereits gelernt haben, können Klammern entweder „eine Gruppe von Dingen zusammen“ oder „eine Capture-Gruppe“ bedeuten. In diesem Fall bedeutet es „eine Gruppe von Dingen zusammen“. Die Zeichen ?! bedeuten „überprüfe vorne und stelle sicher, dass der Inhalt von diesem NICHT das nächste Ding in der Zeichenkette ist!!!!“ Diese Regex wird also das tun, was wir wollen.

Der Inhalt des negativen Lookaheads kann selbst ein regulärer Ausdruck sein. Wenn zum Beispiel unser heimtückischer Anti-Katzen-Vandale versucht, unsere Bemühungen zu vereiteln, indem er eine unterschiedliche Anzahl von Ausrufezeichen an verschiedenen Stellen verwendet, könnten wir stattdessen dies verwenden:

Kätzchen sind süß(?! \(nicht!+\))

In diesem Fall müssen wir 1 oder mehr ! nach dem nicht finden.

Wenn dir das super einfach vorkommt, dann mach weiter und benutze es! Aber wenn nicht, mach dir wirklich keine Gedanken darüber. Wir hätten auch das „If“-Panel in AWB verwenden können, um sicherzustellen, dass unsere Auswahl NICHT die wörtliche Phrase Kätzchen sind süß (nicht!!!) enthält, was uns eine Menge Arbeit und das Auswendiglernen der Syntax erspart hätte.

Lies regular-expressions.info![]

Nur ein Wort der Warnung – diese Seite ist wahnsinnig umfangreich, und sie enthält vor allem eine Menge Dinge, die für dich nicht wirklich relevant sein werden. Ignoriere z. B. Bilanzgruppen, Rekursion und Unterroutinen. Je nachdem, wo du deine Regex schreibst, kann die Syntax auch etwas anders sein. Wenn du eine Regex-Suche im Wiki durchführst, werden einige Dinge wie \b nicht funktionieren. Python verwendet eine andere Syntax für den Verweis auf Capture-Gruppen. Der String-Musterabgleich in Lua ist überhaupt kein regulärer Ausdruck (er ist sehr begrenzt), und du solltest in der Lua-Dokumentation nachlesen, was sie tun. Wenn du allerdings das meiste auf dieser Seite verstanden hast, bist du in einer guten Position, um dir selbst etwas beizubringen! Du kannst deinen gesunden Menschenverstand benutzen, wenn dir etwas zu kompliziert erscheint, als dass es sich lohnen würde, es zu lernen, und du kannst Dinge auslassen, wenn du willst. Denke daran, dass die Regex ein Werkzeug sind, das dir das Leben leichter machen soll – wenn es dir also das Leben schwerer macht, solltest du vielleicht einen anderen Ansatz wählen. Aber Regex sind immer noch sehr mächtig – also viel Spaß damit!

Mehr Hilfe[]

Advertisement