Lesbare reguläre Ausdrücke, ohne an Kraft zu verlieren?

77

Viele Programmierer kennen die Freude, einen schnellen regulären Ausdruck zu erstellen, heutzutage oft mit Hilfe eines Webdienstes oder traditionellerweise bei interaktiver Eingabeaufforderung, oder vielleicht ein kleines Skript zu schreiben, das den regulären Ausdruck in der Entwicklung hat, und eine Sammlung von Testfällen . In beiden Fällen ist der Vorgang iterativ und ziemlich schnell: Hacken Sie so lange an der kryptisch aussehenden Zeichenfolge, bis sie Ihren Wünschen entspricht und sie erfasst und ablehnt, was Sie nicht möchten.

Für einen einfachen Fall könnte das Ergebnis wie folgt aussehen:

Pattern re = Pattern.compile(
  "^\\s*(?:(?:([\\d]+)\\s*:\\s*)?(?:([\\d]+)\\s*:\\s*))?([\\d]+)(?:\\s*[.,]\\s*([0-9]+))?\\s*$"
);

Viele Programmierer wissen auch, wie schwierig es ist, einen regulären Ausdruck zu bearbeiten oder nur einen regulären Ausdruck in einer alten Codebasis zu codieren. Mit ein wenig Bearbeitung, um es aufzuteilen, ist es für jeden, der mit Regexps einigermaßen vertraut ist, immer noch sehr einfach, es über Regexp zu verstehen, und ein Regexp-Veteran sollte sofort sehen, was es tut (antworten Sie am Ende des Beitrags, falls jemand die Übung haben möchte es selbst herauszufinden).

Es muss jedoch nicht viel komplexer werden, damit ein regulärer Ausdruck wirklich nur zum Schreiben verwendet werden kann, und selbst bei sorgfältiger Dokumentation (die natürlich jeder für alle komplexen regulären Ausdrücke ausführt, die er schreibt ...) wird das Ändern der regulären Ausdrücke zu einem Problem entmutigende Aufgabe. Es kann auch eine sehr gefährliche Aufgabe sein, wenn reguläre Ausdrücke nicht sorgfältig auf Einheit getestet werden (aber jeder hat natürlich umfassende Komponententests für all seine komplexen regulären Ausdrücke, sowohl positiv als auch negativ ...).

Also, um es kurz zu machen, gibt es eine Schreib-Lese-Lösung / Alternative für reguläre Ausdrücke, ohne ihre Macht zu verlieren? Wie würde der obige reguläre Ausdruck mit einem alternativen Ansatz aussehen? Jede Sprache ist in Ordnung, obwohl eine mehrsprachige Lösung am besten wäre, sind reguläre Ausdrücke mehrsprachig.


Und dann ist das, was der frühere reguläre Ausdruck tut: parsen Sie eine Zeichenfolge von Zahlen im Format 1:2:3.4, erfassen Sie jede Zahl, wo Leerzeichen erlaubt sind und nur 3erforderlich sind.

hyde
quelle
2
Verwandte Sache auf SO: stackoverflow.com/a/143636/674039
wim
24
Das Lesen / Bearbeiten von Regexen ist eigentlich trivial, wenn Sie wissen, was sie erfassen sollen. Möglicherweise haben Sie von dieser selten verwendeten Funktion der meisten Sprachen namens "Kommentare" gehört. Wenn Sie keinen über einen komplexen regulären Ausdruck setzen, der erklärt, was er tut, zahlen Sie den Preis später. Auch Codeüberprüfung.
TC1
2
Zwei Möglichkeiten, dies zu bereinigen, ohne es tatsächlich in kleinere Stücke zu zerbrechen. Ihre Anwesenheit oder Abwesenheit variiert von Sprache zu Sprache. (1) Erweiterte Regex-Zeilen, bei denen Leerzeichen in der Regex ignoriert werden (es sei denn, es wird ein Escapezeichen verwendet) und ein einzeiliges Kommentarformular hinzugefügt wird, sodass Sie es mit Einrückung, Zeilenabstand und Kommentaren in logische Abschnitte aufteilen können. (2) benannte Erfassungsgruppen, in denen Sie jedem Klammerelement einen Namen geben können, der sowohl eine Selbstdokumentation hinzufügt als auch automatisch einen Hash von Übereinstimmungen auffüllt - viel besser als ein numerisch indiziertes Array von Übereinstimmungen oder $ N-Variablen.
Ben Lee
3
Ein Teil des Problems ist die Regex-Sprache selbst und die schlechten historischen Entscheidungen in ihrem Design, die wie Gepäck mitgeschleppt werden. In einer vernünftigen Sprache sind Gruppierungsklammern lediglich ein syntaktisches Mittel, um den Analysebaum zu formen. In Regex-Implementierungen, die auf Unix zurückgehen, haben sie jedoch eine Semantik: Sie binden Register an Übereinstimmungen mit Unterausdrücken. Dann brauchen Sie etwas kompliziertere, hässlichere Klammern, um eine reine Gruppierung zu erreichen!
Kaz
2
Eigentlich keine praktische Antwort, aber es kann nützlich sein zu erwähnen, dass die Potenz des regulären Ausdrucks genau der eines endlichen Automaten entspricht. Das heißt, reguläre Ausdrücke können dieselbe Klasse von Zeichenfolgen validieren / analysieren, die von endlichen Automaten validiert und analysiert werden. Daher sollte eine von Menschen lesbare Darstellung eines regulären Ausdrucks wahrscheinlich in der Lage sein, schnell ein Diagramm zu erstellen, und ich glaube, dass die meisten textbasierten Sprachen wirklich schlecht darin sind. Deshalb verwenden wir visuelle Werkzeuge für solche Dinge. Werfen Sie einen Blick auf hackingoff.com/compilers/regular-expression-to-nfa-dfa Inspiration zu bekommen.
damix911

Antworten:

80

Einige Leute haben erwähnt, aus kleineren Teilen zu komponieren, aber noch hat niemand ein Beispiel geliefert.

string number = "(\\d+)";
string unit = "(?:" + number + "\\s*:\\s*)";
string optionalDecimal = "(?:\\s*[.,]\\s*" + number + ")?";

Pattern re = Pattern.compile(
  "^\\s*(?:" + unit + "?" + unit + ")?" + number + optionalDecimal + "\\s*$"
);

Nicht am besten lesbar, aber ich glaube, es ist klarer als das Original.

Auch hat C # , um den @Operator, der in einen String , um vorangestellt werden kann , um anzuzeigen , dass es wörtlich genommen werden soll (kein Escape - Zeichen), so numberwäre@"([\d]+)";

Bobson
quelle
Gerade bemerkt nun , wie beide [\\d]+und [0-9]+gerade sein sollte \\d+(na ja, können einige finden [0-9]+mehr lesbar). Ich werde die Frage nicht bearbeiten, aber Sie können diese Antwort korrigieren.
Hyde
@hyde - Guter Fang. Technisch sind sie nicht ganz dasselbe - \dsie stimmen mit allem überein, was als Zahl angesehen wird, auch mit anderen Nummerierungssystemen (Chinesisch, Arabisch usw.), während [0-9]sie nur mit den Standardziffern übereinstimmen. Ich habe es jedoch standardisiert \\dund in das optionalDecimalMuster einbezogen.
Bobson
42

Der Schlüssel zur Dokumentation des regulären Ausdrucks ist die Dokumentation. Viel zu oft werfen die Leute Leitungsgeräusche hinein und belassen es dabei.

Innerhalb von Perl/x unterdrückt der Operator am Ende des regulären Ausdrucks Leerzeichen, sodass der reguläre Ausdruck dokumentiert werden kann.

Der obige reguläre Ausdruck würde dann lauten:

$re = qr/
  ^\s*
  (?:
    (?:       
      ([\d]+)\s*:\s*
    )?
    (?:
      ([\d]+)\s*:\s*
    )
  )?
  ([\d]+)
  (?:
    \s*[.,]\s*([\d]+)
  )?
  \s*$
/x;

Ja, es ist ein bisschen aufwendig mit vertikalen Leerzeichen, obwohl man es verkürzen könnte, ohne zu viel Lesbarkeit zu opfern.

Und was der frühere reguläre Ausdruck dann tut, ist Folgendes: Analysieren Sie eine Folge von Zahlen im Format 1: 2: 3.4, wobei jede Zahl erfasst wird, wobei Leerzeichen zulässig sind und nur 3 erforderlich sind.

Wenn man sich diesen regulären Ausdruck ansieht, kann man sehen, wie es funktioniert (und was nicht). In diesem Fall stimmt dieser reguläre Ausdruck mit der Zeichenfolge überein 1.

Ähnliche Ansätze können in einer anderen Sprache gewählt werden. Die Option python re.VERBOSE funktioniert dort.

Perl6 (das obige Beispiel war für Perl5) führt dies mit dem Konzept der Regeln weiter, das zu noch leistungsfähigeren Strukturen führt als das PCRE (es bietet Zugriff auf andere Grammatiken (kontextfrei und kontextsensitiv) als nur reguläre und erweiterte reguläre).

In Java (wo dieses Beispiel herkommt) kann man Zeichenkettenverkettung verwenden, um den regulären Ausdruck zu bilden.

Pattern re = Pattern.compile(
  "^\\s*"+
  "(?:"+
    "(?:"+
      "([\\d]+)\\s*:\\s*"+  // Capture group #1
    ")?"+
    "(?:"+
      "([\\d]+)\\s*:\\s*"+  // Capture group #2
    ")"+
  ")?"+ // First groups match 0 or 1 times
  "([\\d]+)"+ // Capture group #3
  "(?:\\s*[.,]\\s*([0-9]+))?"+ // Capture group #4 (0 or 1 times)
  "\\s*$"
);

Zugegebenermaßen führt dies zu viel mehr "Verwirrung in der Zeichenfolge, kann leichter gelesen (insbesondere mit Syntaxhervorhebung bei den meisten IDEs) und dokumentiert werden.

Der Schlüssel liegt darin, die Kraft zu erkennen und einmal zu schreiben, in die reguläre Ausdrücke häufig fallen. Das Schreiben des Codes, um dies defensiv zu vermeiden, damit der reguläre Ausdruck klar und verständlich bleibt, ist der Schlüssel. Wir formatieren Java-Code aus Gründen der Klarheit - reguläre Ausdrücke unterscheiden sich nicht, wenn die Sprache Ihnen die Möglichkeit dazu bietet.


quelle
13
Es gibt einen großen Unterschied zwischen "Dokumentieren" und "Zeilenumbrüchen hinzufügen".
4
@JonofAllTrades Den Code lesbar zu machen, ist der erste Schritt zu allem. Wenn Sie Zeilenumbrüche hinzufügen, können Sie auch Kommentare für diese Teilmenge der RE in derselben Zeile einfügen (was bei einer einzelnen langen Zeile mit regulären Ausdrücken schwieriger ist).
2
@ JonofAllTrades, ich widerspreche ziemlich stark. Das "Dokumentieren" und das "Hinzufügen von Zeilenumbrüchen" unterscheiden sich nicht darin, dass beide denselben Zweck erfüllen - wodurch der Code verständlicher wird. Und für schlecht formatierten Code ist das Hinzufügen von Zeilenumbrüchen wesentlich sinnvoller als das Hinzufügen von Dokumentation.
Ben Lee
2
Das Hinzufügen von Zeilenumbrüchen ist ein Anfang, macht jedoch etwa 10% des Auftrags aus. Andere Antworten geben weitere Einzelheiten, was hilfreich ist.
26

Der "ausführliche" Modus, der von einigen Sprachen und Bibliotheken angeboten wird, ist eine der Antworten auf diese Bedenken. In diesem Modus wird das Leerzeichen in der Regexp-Zeichenfolge entfernt (Sie müssen es also verwenden \s), und Kommentare sind möglich. Hier ist ein kurzes Beispiel in Python, das dies standardmäßig unterstützt:

email_regex = re.compile(r"""
    ([\w\.\+]+) # username (captured)
    @
    \w+         # minimal viable domain part
    (?:\.w+)    # rest of the domain, after first dot
""", re.VERBOSE)

In jeder Sprache, in der dies nicht der Fall ist, sollte die Implementierung eines Übersetzers vom ausführlichen in den "normalen" Modus eine einfache Aufgabe sein. Wenn Sie sich Sorgen über die Lesbarkeit Ihrer regulären Ausdrücke machen, würden Sie diese Zeitinvestition wahrscheinlich ziemlich leicht rechtfertigen.

Xion
quelle
15

In jeder Sprache, in der reguläre Ausdrücke verwendet werden, können Sie sie aus einfacheren Blöcken zusammensetzen, um das Lesen zu vereinfachen. Bei allem, was komplizierter als Ihr Beispiel ist, sollten Sie diese Option auf jeden Fall nutzen. Das besondere Problem mit Java und vielen anderen Sprachen ist, dass sie reguläre Ausdrücke nicht als "erstklassige" Bürger behandeln, sondern dass sie sich über String-Literale in die Sprache einschleichen müssen. Dies bedeutet, dass viele Anführungszeichen und umgekehrte Schrägstriche nicht Teil der Regex-Syntax sind und die Lesbarkeit beeinträchtigen. Außerdem können Sie nicht viel besser lesbar werden, ohne Ihre eigene Minisprache und Ihren eigenen Interpreter zu definieren.

Der prototypisch bessere Weg, reguläre Ausdrücke zu integrieren, war natürlich Perl mit seiner Whitespace-Option und den Regex-Anführungszeichen-Operatoren. Perl 6 erweitert das Konzept des Aufbaus von regulären Ausdrücken von Teilen zu rekursiven Grammatiken, was in der Anwendung so viel besser ist, als es wirklich überhaupt nicht zu vergleichen. Die Sprache mag das Boot der Aktualität verfehlt haben, aber ihre reguläre Unterstützung war The Good Stuff (tm).

Kilian Foth
quelle
1
Meinen Sie mit "einfacheren Blöcken", die zu Beginn der Antwort erwähnt wurden, nur die Verkettung von Zeichenfolgen oder etwas Fortgeschritteneres?
Hyde
7
Ich wollte Unterausdrücke als kürzere Zeichenfolgenliterale definieren, sie lokalen Variablen mit aussagekräftigen Namen zuweisen und dann verketten. Ich finde, die Namen sind für die Lesbarkeit wichtiger als nur die Verbesserung des Layouts.
Kilian Foth
11

Ich verwende gerne Expresso: http://www.ultrapico.com/Expresso.htm

Diese kostenlose Anwendung hat die folgenden Funktionen, die ich im Laufe der Zeit nützlich finde:

  • Sie können Ihren regulären Ausdruck einfach kopieren und einfügen, und die Anwendung analysiert ihn für Sie
  • Sobald Ihr regulärer Ausdruck geschrieben ist, können Sie ihn direkt in der Anwendung testen (die Anwendung gibt Ihnen die Liste der Erfassungen, Ersetzungen ...).
  • Sobald Sie es getestet haben, generiert es den C # -Code, um es zu implementieren (beachten Sie, dass der Code die Erläuterungen zu Ihrem regulären Ausdruck enthält).

Mit dem soeben eingereichten regulären Ausdruck würde dies beispielsweise so aussehen: Beispielbildschirm mit dem ursprünglich angegebenen regulären Ausdruck

Natürlich ist es tausend Worte wert, es zu versuchen, es zu beschreiben. Bitte beachten Sie auch, dass ich in irgendeiner Weise mit dem Editor dieser Anwendung verwandt bin.

E. Jaep
quelle
4
Würde es Ihnen etwas ausmachen, dies näher zu erläutern - wie und warum wird die gestellte Frage beantwortet? "Nur-Link-Antworten" sind bei Stack Exchange nicht ganz willkommen
Mittwoch,
5
@gnat Entschuldigung. Du hast absolut recht. Ich hoffe, dass meine bearbeitete Antwort weitere Einblicke bietet.
E. Jaep
9

Für einige Dinge kann es hilfreich sein, nur eine Grammatik wie BNF zu verwenden. Diese können viel einfacher zu lesen sein als reguläre Ausdrücke. Ein Tool wie GoldParser Builder kann dann die Grammatik in einen Parser umwandeln, der das schwere Heben für Sie erledigt.

Die Grammatiken BNF, EBNF usw. können viel einfacher zu lesen und zu erstellen sein als komplizierte reguläre Ausdrücke. GOLD ist ein Werkzeug für solche Dinge.

Der unten stehende c2-Wiki-Link enthält eine Liste möglicher Alternativen, die gegoogelt werden können, einschließlich einiger Diskussionen darüber. Es ist im Grunde ein "Siehe auch" -Link, um meine Grammatik-Engine-Empfehlung zu vervollständigen:

Alternativen zu regulären Ausdrücken

Unter "Alternative" wird "semantisch äquivalente Einrichtung mit unterschiedlicher Syntax" verstanden. Es gibt mindestens die folgenden Alternativen zu / mit RegularExpressions:

  • Grundlegende reguläre Ausdrücke
  • "Erweiterte" reguläre Ausdrücke
  • Perl-kompatible reguläre Ausdrücke
  • ... und viele andere Varianten ...
  • SNOBOL-ähnliche RE-Syntax (SnobolLanguage, IconLanguage)
  • SRE-Syntax (RE als EssExpressions)
  • verschiedene FSM-Syntaces
  • Endlich-Zustands-Schnittgrammatiken (recht ausdrucksstark)
  • ParsingExpressionGrammars, wie in OMetaLanguage und LuaLanguage ( http://www.inf.puc-rio.br/~roberto/lpeg/lpeg.html )
  • Der Analysemodus von RebolLanguage
  • ProbabilityBasedParsing ...
Nick P
quelle
Würde es Ihnen etwas ausmachen, mehr darüber zu erklären, was dieser Link bewirkt und wofür er gut ist? "Nur-Link-Antworten" sind bei Stack Exchange nicht ganz willkommen
Mittwoch,
1
Willkommen bei den Programmierern, Nick P. Bitte ignorieren Sie das Downvote / r, aber lesen Sie die Seite auf Meta, auf die @gnat verlinkt hat.
Christoffer Lette
@ Christoffer Lette Schätzen Sie Ihre Antwort. Ich werde versuchen, dies in zukünftigen Beiträgen zu berücksichtigen. @gnat Paulo Scardines Kommentar spiegelt die Absicht meiner Posts wider. Die Grammatiken BNF, EBNF usw. können viel einfacher zu lesen und zu erstellen sein als komplizierte reguläre Ausdrücke. GOLD ist ein Werkzeug für solche Dinge. Der c2-Link enthält eine Liste möglicher Alternativen, die gegoogelt werden können, einschließlich einiger Diskussionen darüber. Es war im Grunde ein "Siehe auch" -Link, um meine Grammatik-Empfehlung zu vervollständigen.
Nick P
6

Dies ist eine alte Frage und ich habe keine Erwähnung von verbalen Ausdrücken gesehen, daher dachte ich, ich würde diese Informationen auch für zukünftige Suchende hier hinzufügen. Verbale Ausdrücke wurden speziell entwickelt, um Regex für den Menschen verständlich zu machen, ohne die symbolische Bedeutung von Regex erlernen zu müssen. Siehe folgendes Beispiel. Ich denke, das macht das Beste, wonach Sie fragen.

// Create an example of how to test for correctly formed URLs
var tester = VerEx()
    .startOfLine()
    .then('http')
    .maybe('s')
    .then('://')
    .maybe('www.')
    .anythingBut(' ')
    .endOfLine();

// Create an example URL
var testMe = 'https://www.google.com';

// Use RegExp object's native test() function
if (tester.test(testMe)) {
    alert('We have a correct URL '); // This output will fire}
} else {
    alert('The URL is incorrect');
}

console.log(tester); // Outputs the actual expression used: /^(http)(s)?(\:\/\/)(www\.)?([^\ ]*)$/

Dieses Beispiel ist für Javascript. Sie können diese Bibliothek jetzt für viele Programmiersprachen finden.

Parivar Saraff
quelle
2
Das ist fantastisch!
Jeremy Thompson
3

Der einfachste Weg wäre, immer noch Regex zu verwenden, aber Ihren Ausdruck aus einfacheren Ausdrücken mit beschreibenden Namen zu erstellen, z. B. http://www.martinfowler.com/bliki/ComposedRegex.html (und ja, das ist von string concat).

Alternativ können Sie auch eine Parser-Kombinator-Bibliothek verwenden, z. B. http://jparsec.codehaus.org/ , mit der Sie einen vollständig rekursiven anständigen Parser erhalten. Auch hier kommt die wahre Kraft aus der Komposition (diesmal aus der funktionalen Komposition).

jk.
quelle
3

Ich dachte, es wäre wert, Logstashs Grok- Ausdrücke zu erwähnen . Grok baut auf der Idee auf, lange Parsing-Ausdrücke aus kürzeren zusammenzusetzen. Es ermöglicht das bequeme Testen dieser Bausteine ​​und ist mit über 100 häufig verwendeten Mustern vorverpackt . Abgesehen von diesen Mustern können alle regulären Ausdrücke verwendet werden.

Das oben in grok ausgedrückte Muster ist (ich habe es in der Debugger-App getestet, aber es könnte fehlerhaft sein):

"(( *%{NUMBER:a} *:)? *%{NUMBER:b} *:)? *%{NUMBER:c} *(. *%{NUMBER:d} *)?"

Die optionalen Teile und Leerzeichen lassen es etwas hässlicher erscheinen als sonst, aber sowohl hier als auch in anderen Fällen kann die Verwendung von grok das Leben schöner machen.

yoniLavi
quelle
2

In F # haben Sie das Modul FsVerbalExpressions . Es erlaubt Ihnen, Regexes aus verbalen Ausdrücken zusammenzustellen, es hat auch einige vorgefertigte Regexes (wie URL).

Eines der Beispiele für diese Syntax lautet wie folgt:

let groupName =  "GroupNumber"

VerbEx()
|> add "COD"
|> beginCaptureNamed groupName
|> any "0-9"
|> repeatPrevious 3
|> endCapture
|> then' "END"
|> capture "COD123END" groupName
|> printfn "%s"

// 123

Wenn Sie mit der F # -Syntax nicht vertraut sind, ist groupName die Zeichenfolge "GroupNumber".

Dann erstellen sie einen verbalen Ausdruck (VerbEx), den sie als "COD (? <GroupNumber> [0-9] {3}) END" konstruieren. Was sie dann an der Zeichenkette "COD123END" testen, wo sie die benannte Erfassungsgruppe "GroupNumber" erhalten. Dies ergibt 123.

Ich finde die normale Regex ehrlich gesagt viel einfacher zu verstehen.

CodeMonkey
quelle
-2

Verstehe zunächst, dass Code, der nur funktioniert, schlechter Code ist. Guter Code muss auch alle aufgetretenen Fehler genau melden.

Wenn Sie beispielsweise eine Funktion schreiben, mit der Bargeld von einem Benutzerkonto auf ein anderes Benutzerkonto übertragen wird. Sie würden nicht einfach einen "bearbeiteten oder fehlgeschlagenen" Booleschen Wert zurückgeben, da dies dem Anrufer keine Vorstellung davon gibt, was schief gelaufen ist, und es dem Anrufer nicht ermöglicht, den Benutzer ordnungsgemäß zu informieren. Stattdessen haben Sie möglicherweise eine Reihe von Fehlercodes (oder eine Reihe von Ausnahmen): Zielkonto nicht gefunden, nicht genügend Guthaben im Quellkonto, Berechtigung verweigert, keine Verbindung zur Datenbank möglich, zu viel Last (später erneut versuchen) usw .

Denken Sie nun an das Beispiel "Analysieren einer Zahlenfolge im Format 1: 2: 3.4". Alles, was der Regex tut, ist das Melden eines "Bestanden / Nicht Bestanden", bei dem dem Benutzer kein angemessenes Feedback angezeigt werden kann (unabhängig davon, ob es sich um eine Fehlermeldung in einem Protokoll oder eine interaktive Benutzeroberfläche handelt, in der die Fehler rot als angezeigt werden) Benutzertypen oder was auch immer). Welche Arten von Fehlern werden nicht richtig beschrieben? Falsches Zeichen in der ersten Nummer, erste Nummer zu groß, fehlender Doppelpunkt nach der ersten Nummer usw.

Um "schlechten Code, der nur funktioniert" in "guten Code, der ausreichend beschreibende Fehler liefert" umzuwandeln, müssen Sie den regulären Ausdruck in viele kleinere reguläre Ausdrücke aufteilen (normalerweise sind reguläre Ausdrücke so klein, dass es einfacher ist, sie ohne reguläre Ausdrücke auszuführen) ).

Das Lesen / Warten des Codes ist nur eine zufällige Folge des Erhalts des Codes.

Brendan
quelle
6
Wahrscheinlich keine gute Annahme. Meins ist, weil A) dies nicht die Frage anspricht ( wie man es lesbar macht?), B) reguläre Ausdrucksübereinstimmung ist bestanden / nicht bestanden, und wenn Sie es bis zu dem Punkt aufschlüsseln, an dem Sie genau sagen können, warum es fehlgeschlagen ist, Sie Verliere viel Kraft und Geschwindigkeit und erhöhe die Komplexität. C) Es gibt keinen Hinweis auf die Möglichkeit, dass das Match fehlschlägt - es geht einfach darum, den Regex lesbar zu machen. Wenn Sie die Kontrolle über die eingehenden Daten haben und / oder diese vorab validieren, können Sie davon ausgehen, dass sie gültig sind.
Bobson
A) Durch Zerlegen in kleinere Teile wird es besser lesbar (als Folge davon, dass es gut ist). C) Wenn unbekannte / nicht validierte Zeichenfolgen in eine Software eingegeben werden, analysiert ein vernünftiger Entwickler (mit Fehlerberichterstattung) an diesem Punkt die Daten und konvertiert sie in ein Formular, das kein erneutes Parsen erfordert. Danach ist Regex nicht mehr erforderlich. B) ist Unsinn, der nur für fehlerhaften Code gilt (siehe Punkte A und C).
Brendan
Wenn man von Ihrem C: Was ist, wenn dies ist seine Validierungslogik? Der OP-Code könnte genau das sein, was Sie vorschlagen - die Eingabe validieren, melden, wenn sie nicht gültig ist, und in eine verwendbare Form konvertieren (über die Captures). Wir haben nur den Ausdruck selbst. Wie würden Sie vorschlagen, es anders als mit einem regulären Ausdruck zu analysieren? Wenn Sie Beispielcode hinzufügen, der das gleiche Ergebnis erzielt, werde ich meine Downvote entfernen.
Bobson
Wenn dies "C: Validieren (mit Fehlerberichterstattung)" ist, handelt es sich um einen fehlerhaften Code, da die Fehlerberichterstattung fehlerhaft ist. Wenn es fehlschlägt; War es, weil der String NULL war oder weil die erste Zahl zu viele Ziffern hatte oder weil das erste Trennzeichen nicht :? Stellen Sie sich einen Compiler vor, der nur eine Fehlermeldung ("ERROR") hatte, die zu dumm war, um den Benutzer über das Problem zu informieren. Stellen Sie sich jetzt Tausende von Websites vor, die genauso dumm sind und (z. B.) "Schlechte E-Mail-Adresse" und nichts mehr anzeigen.
Brendan
Stellen Sie sich außerdem einen halb ausgebildeten Helpdesk-Bediener vor, der von einem völlig ungeschulten Benutzer einen Fehlerbericht erhält, der besagt: Software funktioniert nicht mehr - Die letzte Zeile im Protokoll der Software lautet "FEHLER: Extrahierung der Nebenversionsnummer aus Versionszeichenfolge '1: 2-3.4 fehlgeschlagen "(voraussichtlicher Doppelpunkt nach der zweiten Ziffer)"
Brendan