Ähnlich wie bei unseren Threads für sprachspezifische Golftipps: Was sind allgemeine Tricks, um reguläre Ausdrücke zu verkürzen?
Ich kann drei Gebrauch von regex sehen , wenn es um Golf geht: klassische regex Golf ( „hier ist eine Liste , die übereinstimmen sollten, und hier ist eine Liste , die fehlschlagen sollte“), Regex zu lösen Rechenprobleme und reguläre Ausdrücke als Teile der verwendeten größerer Golf Code. Sie können gerne Tipps zu einigen oder allen dieser Themen veröffentlichen. Wenn Ihr Tipp auf einen oder mehrere Geschmacksrichtungen beschränkt ist, geben Sie diese bitte oben an.
Halten Sie sich bitte wie gewohnt an einen Tipp (oder eine Familie eng verwandter Tipps) pro Antwort, damit die nützlichsten Tipps durch Abstimmung nach oben gelangen können.
quelle
Antworten:
Wenn nicht zu entkommen
Diese Regeln gelten für die meisten Geschmacksrichtungen, wenn nicht für alle:
]
muss nicht entkommen, wenn es nicht passt.{
und}
brauchen nicht zu fliehen, wenn sie nicht Teil einer Wiederholung sind, zB{a}
Streichhölzer im{a}
wahrsten Sinne des Wortes. Auch wenn Sie so etwas abgleichen wollen{2}
, müssen Sie nur einer davon entkommen, z{2\}
.In Charakterklassen:
]
Es muss nicht maskiert werden, wenn es das erste Zeichen in einem Zeichensatz ist, z. B.[]abc]
eines von]abc
oder wenn es das zweite Zeichen nach einem ist^
, z . B.[^]]
alles andere als]
. (Bemerkenswerte Ausnahme: ECMAScript-Geschmack!)[
muss überhaupt nicht entkommen. Zusammen mit dem obigen Tipp bedeutet dies, dass Sie beide Klammern der fürchterlich kontraintuitiven Zeichenklasse zuordnen können[][]
.^
Es muss nicht maskiert werden, wenn es nicht das erste Zeichen in einem Zeichensatz ist, z[ab^c]
.-
nicht entkommen nicht brauchen , wenn es entweder das erste (zweite nach einem^
) oder letztes Zeichen in einem Zeichensatz, zum Beispiel[-abc]
,[^-abc]
oder[abc-]
.Es müssen keine anderen Zeichen innerhalb einer Zeichenklasse maskiert werden, auch wenn es sich um Metazeichen außerhalb von Zeichenklassen handelt (mit Ausnahme des umgekehrten Schrägstrichs
\
).Auch in einigen Geschmacksrichtungen
^
und$
werden buchstäblich abgeglichen, wenn sie sich nicht am Anfang bzw. Ende des regulären Ausdrucks befinden.(Danke an @ MartinBüttner für das Ausfüllen einiger Details)
quelle
[.]
). Ein normaler Escape-Vorgang würde in diesem Fall 1 Byte sparen\.
[
in Java ein Escapezeichen gesetzt werden muss. Ich bin mir jedoch nicht sicher, ob es sich um eine Intensivstation (für Android und iOS) oder um .NET handelt.Ein einfacher regulärer Ausdruck, der allen druckbaren Zeichen in der ASCII- Tabelle entspricht.
quelle
Kennen Sie Ihre Regex-Aromen
Es gibt eine überraschende Anzahl von Menschen, die glauben, dass reguläre Ausdrücke im Wesentlichen sprachunabhängig sind. Tatsächlich gibt es jedoch erhebliche Unterschiede zwischen den Geschmacksrichtungen, und besonders für Codegolf ist es gut, einige davon und ihre interessanten Merkmale zu kennen, damit Sie für jede Aufgabe die beste auswählen können. Hier finden Sie eine Übersicht über einige wichtige Geschmacksrichtungen und was sie von anderen unterscheidet. (Diese Liste kann nicht wirklich vollständig sein, aber lassen Sie mich wissen, wenn ich etwas wirklich Auffälliges verpasst habe.)
Perl und PCRE
Ich werfe diese in einen Topf, da ich mit dem Perl-Geschmack nicht allzu vertraut bin und sie größtenteils gleichwertig sind (PCRE ist schließlich für Perl-kompatible reguläre Ausdrücke). Der Hauptvorteil der Perl-Variante besteht darin, dass Sie Perl-Code tatsächlich aus dem regulären Ausdruck und der Substitution aufrufen können.
(?(group)yes|no)
.\l
,\u
,\L
und\U
.\G
um eine Übereinstimmung mit dem Ende der vorherigen Übereinstimmung zu verankern.\K
um den Beginn des Spiels zurückzusetzen\Q...\E
längere Serien von Charakteren zu entkommen. Nützlich, wenn Sie versuchen, eine Zeichenfolge zu finden, die viele Metazeichen enthält..NETZ
Dies ist wahrscheinlich der stärkste Geschmack mit nur sehr wenigen Nachteilen.
[\w-[aeiou]]
\d
sind Unicode-fähig.Ein wichtiges Manko beim Golfen ist, dass es keine Possessive Quantifiers wie einige andere Flavours unterstützt. Stattdessen
.?+
musst du schreiben(?>.?)
.Java
.*
von wo aus Sie jetzt einen Lookahead wie starten können(?<=(?=lookahead).*)
.\Q...\E
wie in Perl / PCRE.Rubin
In neueren Versionen ist diese Variante ähnlich leistungsfähig wie PCRE, einschließlich der Unterstützung von Unterprogrammaufrufen. Wie Java unterstützt es auch die Vereinigung und Überschneidung von Zeichenklassen. Eine Besonderheit ist die eingebaute Zeichenklasse für hexadezimale Ziffern:
\h
(und die negierte\H
).Die nützlichste Funktion zum Golfen ist jedoch, wie Ruby mit Quantifizierern umgeht. Insbesondere ist es möglich, Quantifizierer ohne Klammern zu verschachteln.
.{5,7}+
funktioniert und funktioniert auch.{3}?
. Im Gegensatz zu den meisten anderen Geschmacksrichtungen kann auf die untere Grenze eines Quantifizierers0
verzichtet werden, z . B..{,5}
äquivalent zu.{0,5}
.Wie für Subroutinen, ist der große Unterschied zwischen PCRE der Subroutinen und Rubys Subroutinen, dass Rubys Syntax ein Byte länger
(?n)
vs\g<n>
, aber Rubys Subroutinen können für die Aufnahme verwendet werden, während PCRE Captures nach Unterprogramm beendet zurücksetzt.Schließlich hat Ruby eine andere Semantik für zeilenbezogene Modifikatoren als die meisten anderen Varianten. Der Modifikator, der normalerweise
m
in anderen Geschmacksrichtungen verwendet wird, ist in Ruby immer aktiviert. Also^
und$
passen Sie immer den Anfang und das Ende einer Zeile an, nicht nur den Anfang und das Ende der Zeichenfolge. Dies kann Ihnen ein Byte ersparen, wenn Sie dieses Verhalten benötigen, aber es kostet Sie zusätzliche Bytes, wenn Sie dies nicht tun, da Sie jeweils^
und$
durch\A
und ersetzen müssen\z
. Außerdem wird der normalerweise aufgerufene Modifikators
(der.
Zeilenvorschübe erstellt)m
in Ruby aufgerufen . Dies wirkt sich nicht auf die Anzahl der Bytes aus, sollte jedoch beachtet werden, um Verwirrung zu vermeiden.Python
Python hat einen soliden Geschmack, aber mir sind keine besonders nützlichen Funktionen bekannt, die Sie sonst nirgendwo finden würden.
Es gibt jedoch eine alternative Variante , die das
re
Modul irgendwann ersetzen soll und viele interessante Funktionen enthält. Zusätzlich zur Unterstützung für Rekursion, Lookbehinds variabler Länge und Zeichenklassen-Kombinationsoperatoren verfügt es über die einzigartige Funktion des Fuzzy Matching . Im Wesentlichen können Sie eine Reihe von Fehlern (Einfügungen, Löschungen, Ersetzungen) angeben, die zulässig sind, und die Engine gibt Ihnen auch ungefähre Übereinstimmungen.ECMAScript
Das ECMAScript-Aroma ist sehr begrenzt und daher zum Golfen selten sehr nützlich. Das Einzige, was es zu tun hat, ist die negierte leere Zeichenklasse
[^]
, die mit einem beliebigen Zeichen übereinstimmt, sowie die bedingungslos fehlerhafte leere Zeichenklasse[]
(im Gegensatz zu der üblichen(?!)
). Leider weist der Geschmack keine Merkmale auf, was letzteres für normale Probleme nützlich macht.Lua
Lua hat seinen eigenen, ziemlich einzigartigen Geschmack, der ziemlich begrenzt ist (z. B. kann man nicht einmal Gruppen quantifizieren), aber eine Handvoll nützlicher und interessanter Funktionen enthält.
%b
wird eine sehr kompakte Syntax unterstützt, um ausgewogene Zeichenfolgen abzugleichen. ZB%b()
entspricht a(
und dann alles bis zu einem Matching)
(korrektes Überspringen innerer Matching- Paare).(
und)
kann hier zwei beliebige Zeichen sein.Boost
Boosts Regex-Geschmack ist im Wesentlichen Perls. Es hat jedoch einige nette neue Funktionen für die Ersetzung von Regex, einschließlich Falländerungen und Bedingungen . Letzteres gibt es meines Wissens nur bei Boost.
quelle
.?+
gleichbedeutend mit.*
?Kenne deine Charakterklassen
Die meisten Regex-Varianten haben vordefinierte Zeichenklassen. Stimmt beispielsweise
\d
mit einer Dezimalstelle überein, die drei Byte kürzer ist als[0-9]
. Ja, sie können geringfügig voneinander abweichen, da sie\d
in einigen Varianten auch mit Unicode-Ziffern übereinstimmen. Bei den meisten Herausforderungen macht dies jedoch keinen Unterschied.Hier sind einige Zeichenklassen, die in den meisten Regex-Varianten vorkommen:
Darüber hinaus haben wir auch:
Das sind negierte Versionen der oben genannten.
Achten Sie darauf, Ihren Geschmack für zusätzliche Zeichenklassen zu überprüfen, die es möglicherweise hat. Zum Beispiel hat PCRE
\R
für Zeilenumbrüche und Lua sogar Klassen wie Klein- und Großbuchstaben.(Danke an @HamZa und @ MartinBüttner für diesen Hinweis)
quelle
\R
für Zeilenumbrüche in PCRE.Kümmern Sie sich nicht um Gruppen, die nicht erfassen (außer ...)
Dieser Tipp gilt (zumindest) für alle gängigen Perl-inspirierten Aromen.
Dies mag offensichtlich sein, aber (wenn Sie nicht Golf spielen) ist es empfehlenswert,
(?:...)
wenn immer möglich Gruppen zu verwenden, die keine Eroberungsgruppen sind . Diese beiden zusätzlichen Charaktere?:
sind beim Golfen jedoch verschwenderisch. Verwenden Sie daher einfach Erfassungsgruppen, auch wenn Sie sie nicht rückbeziehen möchten.Es gibt jedoch eine (seltene) Ausnahme: Wenn Sie
10
mindestens dreimal hintereinander auf eine Gruppe verweisen , können Sie tatsächlich Bytes sparen, indem Sie eine frühere Gruppe in eine nicht erfassende Gruppe umwandeln , sodass alle diese zu\10
s werden\9
. (Ähnliche Tricks gelten, wenn Sie die Gruppe11
mindestens fünfmal verwenden.)quelle
$9
anstelle von$10
oder$11
einmal verwendet werden kann, wird ein Byte gespeichert . Das Verwandeln$10
in$9
erfordert eins?:
, also zwei Bytes, sodass Sie drei Sekunden benötigen$10
, um etwas zu speichern. Das Umwandeln$11
in$9
erfordert zwei?:
Sekunden, was vier Bytes entspricht. Sie benötigen also fünf$11
Sekunden, um etwas zu speichern (oder fünf von$10
und$11
kombiniert).Rekursion für die Wiederverwendung von Mustern
Eine Handvoll Aromen unterstützen die Rekursion ( meines Wissens Perl, PCRE und Ruby). Selbst wenn Sie nicht versuchen, rekursive Probleme zu lösen, kann diese Funktion viele Bytes in komplizierteren Mustern einsparen . Es ist nicht erforderlich, eine andere (benannte oder nummerierte) Gruppe innerhalb dieser Gruppe selbst anzurufen. Wenn Sie ein bestimmtes Muster haben, das mehrmals in Ihrem regulären Ausdruck vorkommt, gruppieren Sie es einfach und verweisen Sie auf dieses Muster außerhalb dieser Gruppe. Dies unterscheidet sich nicht von einem Unterprogrammaufruf in normalen Programmiersprachen. Also statt
In Perl / PCRE können Sie Folgendes tun:
oder in Ruby:
vorausgesetzt, dies ist die erste Gruppe (natürlich können Sie im rekursiven Aufruf eine beliebige Nummer verwenden).
Beachten Sie, dass dies nicht mit einer Rückverweisung (
\1
) identisch ist . Rückverweise stimmen mit genau der Zeichenfolge überein, mit der die Gruppe zuletzt übereinstimmte. Diese Unterprogrammaufrufe werten das Muster tatsächlich erneut aus. Als Beispiel fürsomeComplexPatternHere
eine längere Zeichenklasse:Das würde sowas passen
Beachten Sie, dass Sie hier keine Rückverweise verwenden können, während das Verhalten beibehalten wird. Ein Rückverweis auf die obige Zeichenfolge schlägt fehl, da
B
und0
und!
nicht identisch sind. Bei Unterprogrammaufrufen wird das Muster jedoch tatsächlich neu bewertet. Das obige Muster ist völlig äquivalent zuErfassung in Unterprogrammaufrufen
Ein Hinweis zur Vorsicht für Perl und PCRE: Wenn die Gruppe
1
in den obigen Beispielen weitere Gruppen enthält, werden sich die Unterprogrammaufrufe nicht an ihre Erfassungen erinnern. Betrachten Sie dieses Beispiel:Dies wird nicht übereinstimmen
da nach der Rückkehr der Unterprogrammaufrufe die neue Erfassung der Gruppe
2
verworfen wird. Stattdessen würde dieses Muster mit dieser Zeichenfolge übereinstimmen:Dies unterscheidet sich von Ruby, wo Subroutinenaufrufe tun ihre Aufnahmen behalten, so das Äquivalent Ruby - regex
(\w(\d):)\2 \g<1>\2 \g<1>\2
die erste der oben genannten Beispielen entsprechen würde.quelle
\1
für Javascript verwenden. Und PHP auch (denke ich).(..)\1
würde passen,abab
aber scheitern,abba
während(..)(?1)
letztere passen. Tatsächlich handelt es sich um einen Unterprogrammaufruf in dem Sinne, dass der Ausdruck erneut angewendet wird, anstatt buchstäblich mit dem übereinzustimmen, mit dem er beim letzten Mal übereinstimmte.(?=a.b.c)(.[0_B!$]){3}d
Ein Match scheitern lassen
Wenn Sie Regex verwenden, um Rechenprobleme zu lösen oder stark unregelmäßige Sprachen abzugleichen, ist es manchmal erforderlich, dass eine Verzweigung des Musters fehlschlägt, unabhängig davon, wo Sie sich in der Zeichenfolge befinden. Der naive Ansatz besteht darin, einen leeren negativen Lookahead zu verwenden:
Der Inhalt (das leere Muster) stimmt immer überein, sodass der negative Lookahead immer fehlschlägt. Meistens gibt es jedoch eine viel einfachere Option: Verwenden Sie einfach ein Zeichen, von dem Sie wissen, dass es niemals in der Eingabe erscheint. Wenn Sie beispielsweise wissen, dass Ihre Eingabe immer nur aus Ziffern besteht, können Sie diese einfach verwenden
oder jedes andere nicht-stellige Nicht-Meta-Zeichen, das einen Fehler verursacht.
Auch wenn Ihre Eingabe möglicherweise Unterzeichenfolgen enthält, gibt es kürzere Wege als
(?!)
. Jede Variante, bei der Anker im Gegensatz zum Ende innerhalb eines Musters erscheinen, kann eine der folgenden 2-Zeichen-Lösungen verwenden:Beachten Sie jedoch , dass einige Aromen behandeln werden
^
und$
als wörtliche Zeichen in diesen Positionen, weil sie offensichtlich nicht wirklich Sinn als Anker machen.In der ECMAScript-Variante gibt es auch die eher elegante 2-Zeichen-Lösung
Dies ist eine leere Zeichenklasse, mit der versucht wird, sicherzustellen, dass das nächste Zeichen eines der Zeichen in der Klasse ist. Die Klasse enthält jedoch keine Zeichen, sodass dies immer fehlschlägt. Beachten Sie, dass dies in keiner anderen Variante funktioniert, da Zeichenklassen normalerweise nicht leer sein können.
quelle
Optimieren Sie Ihre OPs
Wann immer Sie 3 oder mehr Alternativen in Ihrem RegEx haben:
Überprüfen Sie, ob es einen gemeinsamen Start gibt:
Und vielleicht sogar ein gemeinsames Ende?
Hinweis: 3 ist nur der Anfang und würde die gleiche Länge ausmachen, 4+ würde einen Unterschied machen
Aber was ist, wenn nicht alle ein gemeinsames Präfix haben? (Leerzeichen nur zur Verdeutlichung hinzugefügt)
Gruppiere sie, solange die 3+ Regel Sinn macht:
Oder verallgemeinern Sie, ob die Entropie Ihren Verwendungszweck erfüllt:
^ In diesem Fall sind wir sicher, dass wir keine
clue
oder bekommencrown
slack
Ryan
Dies "nach einigen Tests" verbessert auch die Leistung, da es einen Anker bietet , bei dem man beginnen kann.
quelle
aqua|aquamarine
→aqua(|marine)
oderaqua(marine)?
.Dieser ist ziemlich einfach, aber es lohnt sich zu erwähnen:
Wenn Sie feststellen, dass Sie die Zeichenklasse wiederholen
[a-zA-Z]
, können Sie[a-z]
deni
( case- i nsensitive modifier) wahrscheinlich einfach verwenden und an Ihren regulären Ausdruck anhängen .In Ruby sind beispielsweise die folgenden zwei regulären Ausdrücke gleichbedeutend:
/[a-zA-Z]+\d{3}[a-zA-Z]+/
/[a-z]+\d{3}[a-z]/i
- 7 Bytes kürzerIn diesem Fall können die anderen Modifikatoren auch Ihre Gesamtlänge verkürzen. Anstatt dies zu tun:
/(.|\n)/
die jedes Zeichen (weil Punkt nicht Newline überein), verwenden Sie die s ingle-line - Modifikator
s
, das Punktspiel newlines macht././s
- 3 Bytes kürzerIn Ruby gibt es eine Menge eingebauter Zeichenklassen für Regex. Sehen Sie sich diese Seite an und suchen Sie nach "Character Properties".
Ein gutes Beispiel ist das "Währungssymbol". Laut Wikipedia gibt es eine Menge möglicher Währungssymbole, und es wäre sehr teuer, sie in eine Zeichenklasse einzuteilen (
[$฿¢₡Ð₫€.....
]), während Sie jedes davon in 6 Bytes abgleichen können:\p{Sc}
quelle
s
Modifikator nicht unterstützt wird. :( Aber dort können Sie JavaScript proprietären/[^]/
Trick verwenden.(.|\n)
dies in einigen Geschmacksrichtungen nicht funktioniert, da es.
häufig auch nicht zu anderen Arten von Zeilentrennzeichen passt. Die übliche Möglichkeit, dies (ohnes
) zu tun[\s\S]
, sind die gleichen Bytes wie(.|\n)
.Ein einfacher Sprachparser
Sie können einen sehr einfachen Parser mit einem RE wie erstellen
\d+|\w+|".*?"|\n|\S
. Die zuzuordnenden Token sind durch das RE- oder das RE-Zeichen getrennt.Jedes Mal, wenn die RE-Engine versucht, an der aktuellen Position im Text eine Übereinstimmung zu finden, versucht sie das erste Muster, dann das zweite usw. Wenn dies fehlschlägt (z. B. bei einem Leerzeichen hier), fährt sie fort und versucht die Übereinstimmungen erneut . Ordnung ist wichtig. Wenn wir den
\S
Begriff vor dem\d+
Begriff platzieren,\S
würde der zuerst auf ein Nicht-Leerzeichen passen, was unseren Parser beschädigen würde.Der
".*?"
String-Matcher verwendet einen nicht gierigen Modifikator, sodass immer nur ein String abgeglichen wird. Wenn Ihr RE keine nicht gierigen Funktionen hat, können Sie"[^"]*"
die entsprechenden Funktionen verwenden.Python-Beispiel:
Golfed Python Beispiel:
Sie können die Muster und ihre Reihenfolge für die Sprache anpassen, die Sie abgleichen möchten. Diese Technik eignet sich gut für JSON, einfaches HTML und numerische Ausdrücke. Es wurde schon oft mit Python 2 erfolgreich verwendet, sollte aber allgemein genug sein, um in anderen Umgebungen zu funktionieren.
quelle
\K
anstatt positiv auszusehenPCRE und Perl unterstützen die Escape-Sequenz
\K
, die den Beginn des Spiels zurücksetzt. Diesab\Kcd
erfordert, dass Ihre Eingabezeichenfolge enthältabcd
, die gemeldete Übereinstimmung jedoch nurcd
.Wenn Sie zu Beginn Ihres Musters einen positiven Lookbehind verwenden (was wahrscheinlich der wahrscheinlichste Ort ist), können Sie in den meisten Fällen
\K
stattdessen 3 Bytes verwenden und sparen:Dies ist für die meisten Zwecke äquivalent , jedoch nicht vollständig. Die Unterschiede bringen sowohl Vor- als auch Nachteile mit sich:
(?<=ab*)
. Aber mit können\K
Sie jede Art von Muster davor stellen! Funktioniert alsoab*\K
. Dies macht diese Technik in den Fällen, in denen sie anwendbar ist, erheblich leistungsfähiger.\K
dieses Teils wird der reguläre Ausdruck wie alles andere zurückverfolgt.Nachteil: Wie Sie wahrscheinlich wissen, können sich mehrere Übereinstimmungen einer Regex nicht überschneiden. Häufig werden Lookarounds verwendet, um diese Einschränkung teilweise zu umgehen, da der Lookahead einen Teil der Zeichenfolge überprüfen kann, der bereits von einer früheren Übereinstimmung verwendet wurde. Also , wenn Sie wollten alle die Zeichen übereinstimmen, gefolgt
ab
Sie verwenden könnten(?<=ab).
. Angesichts der Eingabedas würde zum zweiten
a
und zum zweiten passenc
. Dies kann nicht mit reproduziert werden\K
. Wenn Sie verwendet habenab\K.
, würden Sie nur das erste Match erhalten, da sich das jetztab
nicht in einem Lookaround befindet.quelle
\K
Escape-Sequenz innerhalb einer positiven Zusicherung verwendet, kann der gemeldete Beginn einer erfolgreichen Übereinstimmung größer sein als das Ende der Übereinstimmung.ababc
es keine Möglichkeit gibt, sowohl die zweitea
als auch diec
mit zu vergleichen\K
. Sie erhalten nur eine Übereinstimmung.\G
.
Spiel vom letzten Match tatsächlich eines wara
.Passend zu jedem Charakter
In der ECMAScript- Variante fehlen die
s
Modifikatoren, mit denen.
jedes Zeichen (einschließlich Zeilenumbrüchen) übereinstimmt. Dies bedeutet, dass es keine Einzelzeichenlösung gibt, um vollständig beliebige Zeichen abzugleichen. Die Standardlösung in anderen Geschmacksrichtungen (wenn mans
aus irgendeinem Grund nicht verwenden möchte ) ist[\s\S]
. Allerdings ist ECMAScript der einzige Geschmack (meines Wissens) , die Klassen leer Zeichen unterstützt, und hat daher eine viel kürzere Alternative:[^]
. Dies ist eine negierte leere Zeichenklasse - das heißt, sie stimmt mit jedem beliebigen Zeichen überein.Auch für andere Geschmacksrichtungen können wir aus dieser Technik lernen: Wenn wir nicht verwenden möchten
s
(z. B. weil wir immer noch die übliche Bedeutung von.
an anderen Stellen benötigen ), kann es immer noch einen kürzeren Weg geben, um sowohl Zeilenvorschub- als auch druckbare Zeichen abzugleichen. vorausgesetzt, es gibt ein Zeichen, von dem wir wissen, dass es nicht in der Eingabe erscheint. Angenommen, wir verarbeiten Zahlen, die durch Zeilenumbrüche begrenzt sind. Dann können wir jedes Zeichen mit abgleichen[^!]
, da wir wissen, dass!
das niemals Teil der Zeichenkette sein wird. Dies spart zwei Bytes gegenüber dem naiven[\s\S]
oder[\d\n]
.quelle
\N
bedeutet dies genau, was.
außerhalb des/s
Modus bedeutet, es sei denn, es wird nicht von einem Modus beeinflusst.Verwenden Sie Atomgruppen und Possessivquantifikatoren
Ich fand Atomgruppen (
(?>...)
) und possessive Quantoren (?+
,*+
,++
,{m,n}+
) manchmal sehr nützlich für den Golfsport. Es stimmt mit einer Zeichenfolge überein und lässt später kein Zurückverfolgen zu. Es wird also nur die erste übereinstimmende Zeichenfolge gefunden, die von der Regex-Engine gefunden wird.Beispiel: Um eine Zeichenfolge mit einer ungeraden Anzahl von
a
Zeichen am Anfang abzugleichen, auf die keine weiteren folgena
, können Sie Folgendes verwenden:Auf diese Weise können Sie Dinge wie
.*
frei verwenden, und wenn es eine offensichtliche Übereinstimmung gibt, wird es keine andere Möglichkeit geben, zu viele oder zu wenige Zeichen zu finden, wodurch Ihr Muster möglicherweise beschädigt wird.In .NET Regex (das keine besitzergreifenden Quantifizierer hat) können Sie dies verwenden, um Gruppe 1 das größte Vielfache von 3 (mit maximal 30) Malen (nicht sehr gut golfen) zu platzieren:
quelle
Vergessen Sie eine erfasste Gruppe nach einem Unterausdruck (PCRE)
Für diesen Regex:
Wenn Sie \ 2 nach Gruppe 1 löschen möchten, können Sie die Rekursion verwenden:
Es wird passen,
aa
während das vorherige nicht passt. Manchmal können Sie auch??
oder sogar?
anstelle von verwenden{0}
.Dies kann hilfreich sein, wenn Sie häufig Rekursionen verwendet haben und einige der Rückverweise oder bedingten Gruppen an verschiedenen Stellen in Ihrem regulären Ausdruck vorkamen.
Beachten Sie auch, dass Atomgruppen für Rekursionen in PCRE angenommen werden. Das passt also nicht zu einem Buchstaben
a
:Ich habe es noch nicht in anderen Geschmacksrichtungen probiert.
Für Lookaheads können Sie zu diesem Zweck auch Doppel-Negative verwenden:
quelle
Optionale Ausdrücke
Es ist manchmal nützlich, sich daran zu erinnern
ist meistens das gleiche wie
Es gibt jedoch einen kleinen Unterschied: Im ersten Fall erfasst die Gruppe entweder
abc
oder sie erfasst überhaupt nicht. Der letztere Fall würde einen Rückverweis bedingungslos zum Scheitern bringen. Im zweiten Ausdruck, die Gruppe wird entweder Captureabc
oder eine leere Zeichenfolge, wobei letztere Fall eine Rückreferenzierung machen würde Spiel bedingungslos. Um das letztere Verhalten zu emulieren,?
müssten Sie alles in eine andere Gruppe einschließen, was zwei Bytes kosten würde:Die Version, die verwendet
|
wird , ist auch nützlich, wenn Sie den Ausdruck trotzdem in eine andere Form von Gruppe einschließen möchten und sich nicht um die Erfassung kümmern:Schließlich kann dieser Trick auch auf Unreedy angewendet werden,
?
wo ein Byte sogar in seiner Rohform gespeichert wird (und folglich 3 Bytes, wenn es mit anderen Gruppenformen kombiniert wird):quelle
Mehrere Lookaheads, die immer übereinstimmen (.NET)
Wenn Sie 3 oder mehr Lookahead-Konstrukte haben, die immer übereinstimmen (um Unterausdrücke zu erfassen), oder wenn ein Quantifizierer auf einem Lookahead von etwas anderem gefolgt wird, sollten sie sich in einer nicht unbedingt erfassten Gruppe befinden:
Diese sind kürzer:
wo
a
sollte nicht der Name einer erfassten Gruppe sein. Sie können nicht|
das Übliche inb
undc
ohne ein weiteres Klammerpaar bedeuten .Leider schienen die Bilanzkreise in den Bedingungen fehlerhaft zu sein, was sie in vielen Fällen unbrauchbar machte.
quelle