Frage

Ich habe gerade eine riesige regex für Java gesehen, die gemacht denke ich ein wenig über die Wartbarkeit von regulären Ausdrücken im Allgemeinen. Ich glaube, dass die meisten Menschen - mit Ausnahme einiger Badass PerlMongers - würden zustimmen, dass reguläre Ausdrücke sind kaum wartbar

.

Ich habe darüber nachgedacht, wie diese Situation behoben werden konnte. Bisher ist die vielversprechendste Idee, die ich habe ist mit einem Fluent Interface . Um ein Beispiel zu geben, statt:

Pattern pattern = Pattern.compile("a*|b{2,5}");

ein so etwas schreiben könnte

import static util.PatternBuilder.*

Pattern pattern = string("a").anyTimes().or().string("b").times(2,5).compile();

Pattern alternative = 
  or(
    string("a").anyTimes(),
    string("b").times(2,5)
  )
  .compile();

In diesem kurzen Beispiel der gemeinsame Weg regulären Ausdruck zu schaffen ist immer noch gut lesbar ein mittelmäßig talentierten Entwickler. Jedoch denkt über jene gespenstische Ausdrücke, die Füllung zwei oder mehr Zeilen mit je 80 Zeichen. Sicher, die (ausführlich) fließend Schnittstelle würde statt nur zwei verschiedene Linien erfordern, aber ich bin sicher, es wäre viel besser lesbar (daher wartbar) sein.

Nun meine Fragen:

  1. Kennen Sie einen ähnlichen Ansatz zu regulären Ausdrücken?

  2. Sind Sie damit einverstanden, dass dieser Ansatz besser sein könnte als einfache Strings?

  3. Wie würden Sie die API entwerfen?

  4. Sie verwenden würde solch eine saubere Dienstprogramm in Ihren Projekten?

  5. Glaubst du, das würde Spaß machen, zu implementieren? ;)

EDIT: Stellen Sie sich vor, es könne Methoden sein, die auf einer höheren Ebene als einfache Konstrukte wir alle nicht von regex, z.B.

// matches aaaab@example.com - think of it as reusable expressions
Pattern p = string{"a").anyTimes().string("b@").domain().compile();

EDIT - kurze Zusammenfassung der Kommentare:

Es ist interessant, dass die meisten Menschen zu lesen, denken, dass reguläre Ausdrücke sind hier zu bleiben - auch wenn es Tools nimmt sie und smarten Jungs zu lesen, sich zu überlegen, um sie verwaltbar zu machen. Während ich bin nicht sicher, dass ein Fluent Interface ist der beste Weg zu gehen, ich bin sicher, dass einige smart-Ingenieure - wir? ;) - sollten einige Zeit verbringen regulären Ausdrücken eine Sache der Vergangenheit zu machen - es ist genug, dass sie seit 50 Jahren bei uns haben, wissen, nicht denken Sie

OPEN BOUNTY

Die Prämie wird an die beste Idee vergeben (kein Code erforderlich) für einen neuen Ansatz für reguläre Ausdrücke.

EDIT - ein schönes Beispiel:

Hier ist die Art von Muster ich rede - Extra dickes Lob an die erste die in der Lage ist, es zu übersetzen - RegexBuddies erlaubt (es ist von einem Apache-Projekt btw) Extra dickes Lob vergeben chii und mez : es ist ein RFC-konforme E-Mail-Adresse Prüfungsmuster - obwohl sein RFC822 (siehe < a href = "http://www.ex-parrot.com/~pdw/Mail-RFC822-Address.html" rel = "nofollow noreferrer"> ex-parrot.com ), nicht 5322 - nicht sicher, ob es einen Unterschied gibt, obwohl - wenn ja, werde ich Auszeichnung nächste Extra ein dickes Lob für ein Patch passen 5322;)

private static final String pattern = "(?:(?:\\r\\n)?[ \\t])*(?:(?:(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t]"
    + ")+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:"
    + "\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:("
    + "?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ "
    + "\\t]))*\"(?:(?:\\r\\n)?[ \\t])*))*@(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\".\\[\\] \\000-\\0"
    + "31]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\"
    + "](?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+"
    + "(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:"
    + "(?:\\r\\n)?[ \\t])*))*|(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z"
    + "|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)"
    + "?[ \\t])*)*\\<(?:(?:\\r\\n)?[ \\t])*(?:@(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\"
    + "r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?["
    + " \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)"
    + "?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t]"
    + ")*))*(?:,@(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?["
    + " \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*"
    + ")(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t]"
    + ")+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*))*)"
    + "*:(?:(?:\\r\\n)?[ \\t])*)?(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+"
    + "|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r"
    + "\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:"
    + "\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t"
    + "]))*\"(?:(?:\\r\\n)?[ \\t])*))*@(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031"
    + "]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\]("
    + "?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?"
    + ":(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?"
    + ":\\r\\n)?[ \\t])*))*\\>(?:(?:\\r\\n)?[ \\t])*)|(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?"
    + ":(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?"
    + "[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*)*:(?:(?:\\r\\n)?[ \\t])*(?:(?:(?:[^()<>@,;:\\\".\\[\\] "
    + "\\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|"
    + "\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>"
    + "@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\""
    + "(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*))*@(?:(?:\\r\\n)?[ \\t]"
    + ")*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\"
    + "\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?"
    + ":[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\["
    + "\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*))*|(?:[^()<>@,;:\\\".\\[\\] \\000-"
    + "\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|("
    + "?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*)*\\<(?:(?:\\r\\n)?[ \\t])*(?:@(?:[^()<>@,;"
    + ":\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\\[(["
    + "^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\""
    + ".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\\[([^\\[\\"
    + "]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*))*(?:,@(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\".\\"
    + "[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\\[([^\\[\\]\\"
    + "r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\".\\[\\] "
    + "\\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]"
    + "|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*))*)*:(?:(?:\\r\\n)?[ \\t])*)?(?:[^()<>@,;:\\\".\\[\\] \\0"
    + "00-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\"
    + ".|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,"
    + ";:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\"(?"
    + ":[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*))*@(?:(?:\\r\\n)?[ \\t])*"
    + "(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\"."
    + "\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:["
    + "^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]"
    + "]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*))*\\>(?:(?:\\r\\n)?[ \\t])*)(?:,\\s*("
    + "?:(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\"
    + "\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:("
    + "?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=["
    + "\\[\"()<>@,;:\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t"
    + "])*))*@(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t"
    + "])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*)(?"
    + ":\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|"
    + "\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*))*|(?:"
    + "[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\"
    + "]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*)*\\<(?:(?:\\r\\n)"
    + "?[ \\t])*(?:@(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\""
    + "()<>@,;:\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)"
    + "?[ \\t])*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>"
    + "@,;:\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*))*(?:,@(?:(?:\\r\\n)?["
    + " \\t])*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,"
    + ";:\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t]"
    + ")*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\"
    + "\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*))*)*:(?:(?:\\r\\n)?[ \\t])*)?"
    + "(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\"."
    + "\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:"
    + "\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\["
    + "\"()<>@,;:\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])"
    + "*))*@(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])"
    + "+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*)(?:\\"
    + ".(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z"
    + "|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*))*\\>(?:("
    + "?:\\r\\n)?[ \\t])*))*)?;\\s*)";
War es hilfreich?

Lösung

Wie würden Sie die API entwerfen?

würde ich eine Seite aus dem Hibernate Kriterien API borgen. Anstelle der Verwendung von:

string("a").anyTimes().or().string("b").times(2,5).compile()

Verwenden Sie ein Muster wie:

Pattern.or(Pattern.anyTimes("a"), Pattern.times("b", 2, 5)).compile()

Diese Schreibweise ist etwas knapper, und ich fühle, dass es einfacher ist, die Hierarchie / Struktur des Musters zu verstehen. Jede Methode kann entweder eine Zeichenfolge akzeptieren, oder ein Muster Fragment, als erstes Argument.

Kennen Sie einen ähnlichen Ansatz zu regulären Ausdrücken?

Nicht ohne Weiteres, Nr.

Sind Sie damit einverstanden, dass dieser Ansatz könnte besser sein als die Verwendung von einfachen Strings?

Ja, absolutetely ... wenn Sie regex verwenden ist für etwas kompliziert Ferne. Bei sehr kurzen und einfachen Fällen ist eine Zeichenfolge bequeme.

würden Sie verwenden, wie ein ordentliches Dienstprogramm in Ihren Projekten?

Vielleicht, weil es bewiesen wurde / stable ... es in ein größeres Dienstprogramm Projekt wie Apache Commons rollen könnte ein Plus.

Glaubst du, das würde Spaß machen, zu implementieren? ;)

1

Andere Tipps

Martin Fowler vorschlagen eine andere Strategie . Und zwar unter sinnvolle Teile der Regex und ersetzen sie durch Variablen. Er verwendet folgendes Beispiel:

 "^score\s+(\d+)\s+for\s+(\d+)\s+nights?\s+at\s+(.*)" 

wird

   String scoreKeyword = "^score\s+";
   String numberOfPoints = "(\d+)";
   String forKeyword = "\s+for\s+";
   String numberOfNights = "(\d+)";
   String nightsAtKeyword = "\s+nights?\s+at\s+";
   String hotelName = "(.*)";

   String pattern = scoreKeyword + numberOfPoints +
      forKeyword + numberOfNights + nightsAtKeyword + hotelName;

Welche viel besser lesbar und wartbar ist.

Das Ziel des vorigen Beispiels war NumberOfPoints, numberOfNights und namen aus einer Liste von Strings wie zu analysieren:

score 400 for 2 nights at Minas Tirith Airport

Es könnte ohne regex Erfahrung für jemanden etwas einfacher sein, aber nachdem jemand Ihr System lernt, wird er nach wie vor nicht in der Lage sein, an anderer Stelle eine normale regex zu lesen.

Auch ich denke, Ihre Version härter ist für einen regulären Ausdruck Experten zu lesen.

Ich würde empfehlen, die Regex wie diese mit Anmerkungen versehen:

Pattern pattern = Pattern.compile(
  "a*     # Find 0 or more a        \n" +
  "|      # ... or ...              \n" +
  "b{2,5} # Find between 2 and 5 b  \n",
Pattern.COMMENTS);

Das ist einfach für jede Erfahrungsstufe zu lesen, und für den unerfahrenen, es lehrt regex zugleich. Auch können die Kommentare an die Situation angepasst werden, um die Geschäftsregeln hinter dem regulären Ausdruck zu erklären, und nicht nur die Struktur.

Auch ein Tool wie RegexBuddy können Ihre regex nehmen und übersetzen sie in:

Match either the regular expression below (attempting the next alternative only if this one fails) «a*»
   Match the character "a" literally «a*»
      Between zero and unlimited times, as many times as possible, giving back as needed (greedy) «*»
Or match regular expression number 2 below (the entire match attempt fails if this one fails to match) «b{2,5}»
   Match the character "b" literally «b{2,5}»
      Between 2 and 5 times, as many times as possible, giving back as needed (greedy) «{2,5}»

Das ist eine faszinierende Konzept, aber wie es präsentiert wird, gibt es ein paar Fehler.

Aber erste Antworten auf die zentralen Fragen gestellt:

Nun meine Fragen:

1. Kennen Sie einen ähnlichen Ansatz zu regulären Ausdrücken?

Keine, die nicht bereits erwähnt haben. Und diejenigen, fand ich heraus, über die Frage und Antworten zu lesen.

2. Stimmen Sie zu, dass dieser Ansatz könnte besser sein als die Verwendung von einfachen Strings?

Wenn es so funktioniert, wäre es auf jeden Fall macht die Dinge viel einfacher zu debuggen.

3. Wie würden Sie die API entwerfen?

meine Notizen im nächsten Abschnitt. Ich nehme Ihre Beispiele und die verknüpfte NET-Bibliothek als Ausgangspunkt.

4. Würden Sie eine solche ordentlich Dienstprogramm in Ihren Projekten verwenden?

Undecided. Ich habe kein Problem Arbeits mit der aktuellen Version von kryptischen regelmäßig Ausdrücke. Und ich würde ein Werkzeug benötigt bestehende reguläre Ausdrücke auf die fließende Sprachversion zu umwandeln.

5. Umsetzung Glaubst du, das würde Spaß sein? ;)

Ich würde genießt die höhere Ebene herauszufinden, wie, als den eigentlichen Code zu schreiben. Die die Wand des Textes erklärt, dass diese Antwort ist.


Hier sind ein paar Probleme, die ich bemerkt, und die Art und Weise würde ich damit umgehen.

Unklare Struktur.

Ihr Beispiel scheint durch die Verkettung auf Strings einen regulären Ausdruck zu erstellen. Dies ist nicht sehr robust. Ich glaube, dass diese Methoden zu String und Pater / Regex-Objekte hinzugefügt werden sollen, weil es Implementierung und Code sauberer machen. Außerdem ist es die Art und Weise ähnlich sind Reguläre Ausdrücke klassisch definiert.

Nur weil ich nicht sehen kann es andere Art und Weise arbeiten, der Rest meiner Anmerkungen zu der vorgeschlagenen Regelung wird davon ausgegangen, dass alle Methoden wirken auf und Rückkehr Muster Objekte.

Edit: Ich scheine die folgenden Konventionen im gesamten verwendet zu haben. Also habe ich sie geklärt und sie hier nach oben bewegen.

  • Instanzmethoden: Muster Augmentation. zB:. Capturing, Wiederholung, schauen Sie sich um Behauptungen

  • Die Betreiber: Reihenfolge der Operationen. Wechsel, Verkettung

  • Konstanten: Zeichenklassen, Grenzen (Inplace von \ w, $, \ b, usw.)

Wie wird Capturing / Clustering behandelt werden?

Capturing ist ein großer Teil von regulären Ausdrücken.

Ich sehe jedes Objekt Pattern wird intern als Cluster gespeichert. (?: Muster) in Perl Bedingungen. für Muster ermöglicht Token leicht mit anderen Stücken ohne störende gemischt und vermengt werden.

Ich erwarte, dass die Erfassung als Instanz-Methode auf einem Muster durchgeführt werden. eine Variable Unter dem passenden String speichern [s] in.

pattern.capture(variable) würde Muster in Variablen speichern. Für den Fall, dass das Capture-Teil eines Ausdrucks ist mehrfach zusammengepaßt werden, Variable sollte ein Array von Strings aller Spiele für Muster enthalten.

Fluent Sprachen können sehr vieldeutig sein.

Fluent Sprachen sind nicht gut auf die rekursive Art von regulären Ausdrücken geeignet. So Berücksichtigung Bedürfnisse der Reihenfolge der Operationen gegeben werden. Nur Verkettung Methoden nicht für sehr komplexe reguläre Ausdrücke zulassen. Genau die Situation, in der ein solches Instrument wäre nützlich.

Does

Pattern pattern = string("a").anyTimes().or().string("b").times(2,5).compile();

produzieren /a*|b{2,5}/ oder /(a*|b){2,5}/?

Wie würde ein solches System Griff verschachtelt Wechsel? ZB: /a*|b(c|d)|e/

Ich sehe drei Wege im Umgang mit Wechsel in regulären Ausdrücken

  1. Als Betreiber: pattern1 or pattern2 => pattern # /pattern1|pattern2/
  2. Als Klassenmethode: Pattern.or( pattern1, pattern2[, pattern3]*) => pattern # /pattern1|patern2|patern3|...|/
  3. Als Beispiel Methode: pattern1.or(pattern2) => pattern # /pattern1|patern2/

würde ich Verkettung auf die gleiche Weise behandeln.

  1. Als Betreiber: pattern1 + pattern2 => pattern # /pattern1pattern2/
  2. Als Klassenmethode: Pattern.concatenate( pattern1, pattern2[, pattern3]*) => pattern # /pattern1patern2patern3.../
  3. Als Beispiel Methode: pattern1.then(pattern2) => pattern # /pattern1patern2/

Wie für häufig verwendete p verlängernatterns

Die vorgeschlagene Regelung verwendet .domain() die eine gemeinsame regex zu sein scheint. Zur Behandlung von benutzerdefinierten Muster als Methoden machen es nicht leicht, neue Muster hinzuzufügen. In einer Sprache wie Java Benutzer der Bibliothek würde die Klasse außer Kraft zu setzen Methoden hinzufügen für häufig verwendetes Muster.

Dies wird durch meinen Vorschlag adressiert jedes Stück als Objekt zu behandeln. Ein Muster-Objekt kann für jede Gebräuchliche regex erzeugt werden wie eine Domäne zum Beispiel entspricht. Aufgrund meiner früheren Gedanken über die Erfassung es nicht allzu schwierig sein würde, um sicherzustellen, dass die Arbeiten für mehrere Kopien des gleichen gemeinsamen Musters erfaßt, die einen aufgenommenen Abschnitt enthält.

Es sollte auch Konstanten für Muster seines passenden verschiedene Charakterklassen.

Null Breite Blick um Behauptungen

Die Erweiterung auf meine Gedanken, dass alle Stücke implizit geclustert werden sollen. Schauen Sie sich um Aussagen sollten nicht allzu schwer sein, zu tun mit einer Instanzmethode.

pattern.zeroWidthLookBehind() würde (?<patten) produzieren.


Dinge, die berücksichtigt werden müssen noch.

  • Rückverweise: Hoffentlich nicht zu hart mit dem Namen Capturing früher diskutiert
  • Wie es tatsächlich umzusetzen. Ich habe nicht die Interna zu viel nachgedacht. Es ist, wo die wirkliche Magie passieren wird.
  • Übersetzung: Es sollte wirklich ein Werkzeug zum und vom klassischen regexs (sagen Perl Dialekt) und das neue System übersetzen sein. Die Übersetzung aus der neuen Regelung könnte ein Teil des Pakets sein

setzen sie alle zusammen, meine vorgeschlagene Version eines Musters, das eine E-Mail-Adresse übereinstimmt:

Pattern domain_label = LETTER_CHARACTER + (LETTER_CHARACTER or "-" or DIGIT_CHARACTER).anyTimes()
Pattern domain = domain_label + ("." + domain_label).anyTimes()
Pattern pattern = (LETTER_CHARACTER + ALPHANUMERIC_CHARACTER + "@" + domain).compile

Im Nachhinein leiht mein Schema stark von Martin Fowler Ansatz im Einsatz. Obwohl ich nicht beabsichtige, für Dinge, diesen Weg zu gehen, ist es auf jeden Fall ein solches System besser verwaltbar werden. Er geht auch auf ein Problem oder zwei mit Fowler-Ansatz (Capturing Reihenfolge).

Mein bescheidener Versuch kann auf GitHub . Obwohl ich es wert denke nicht für einfache Ausdrücke verwenden, macht es eine Reihe von Vorteilen bieten neben der Lesbarkeit Verbesserung:

  • Es kümmert sich um Halterung passende
  • Es Griffe aller ‚speziellen‘ Zeichen zu entkommen, die schnell zu Backslash Hölle führen

Ein paar einfachen Beispiele:

 // Matches a single digit
    RegExBuilder.build(anyDigit()); // "[0-9]"

 // Matches exactly 2 digits
    RegExBuilder.build(exactly(2).of(anyDigit())); // "[0-9]{2}"

 // Matches between 2 and 4 letters
    RegExBuilder.build(between(2,4).of(anyLetter())); // "[a-zA-Z]{2,4}"

Und ein komplizierterer (die mehr oder weniger validates E-Mail-Adressen):

final Token ALPHA_NUM = anyOneOf(range('A','Z'), range('a','z'), range('0','9'));
final Token ALPHA_NUM_HYPEN_UNDERSCORE = anyOneOf(characters('_','-'), range('A','Z'), range('a','z'), range('0','9'));

String regexText = RegExBuilder.build(
 // Before the '@' symbol we can have letters, numbers, underscores and hyphens anywhere
    oneOrMore().of(
        ALPHA_NUM_HYPEN_UNDERSCORE
    ),
    zeroOrMore().of(
        text("."), // Periods are also allowed in the name, but not as the initial character
        oneOrMore().of(
            ALPHA_NUM_HYPEN_UNDERSCORE
        )
    ),
    text("@"),
 // Everything else is the domain name - only letters, numbers and periods here
    oneOrMore().of( 
        ALPHA_NUM
    ),
    zeroOrMore().of(
        text("."), // Periods must not be the first character in the domain
        oneOrMore().of(
            ALPHA_NUM
        )
    ),
    text("."), // At least one period is required
    atLeast(2).of( // Period must be followed by at least 2 letters (this is the TLD)
        anyLetter()
    )
);

Es gibt eine fließend Regexps Bibliothek für .NET.

Kurze Antwort:. Ich habe gesehen, es von einem Fusseln und Kompilieren Winkel genähert, was meiner Meinung nach etwas für diese zu prüfen ist,

Lange Antwort: Die Firma, die ich Arbeit für Marken hardwarebasierte reguläre Ausdrücke Motoren für Enterprise-Content-Anwendungen zu filtern. Denken Sie laufen Antivirus- oder Firewall-Anwendungen auf 20 GB / s direkt in dem Netzwerk-Router, anstatt die Aufnahme wertvolle Server- oder Prozessorzyklen beschleunigt. Die meisten Anti-Virus, Anti-Spam und Firewall-Anwendungen sind eine Reihe von Regex Ausdrücke im Kern.

Wie auch immer, die Art, wie die Regex ist geschrieben hat einen großen Einfluss auf die Leistung des Scan. Sie können regexs auf verschiedene Weise schreiben, das Gleiche zu tun, und einige werden drastisch höhere Leistung haben. Wir haben geschrieben Compiler und Linters für unsere Kunden zu helfen, sie pflegen und stimmen ihre Ausdrücke.

Zurück auf die Frage des OP, anstatt eine völlig neue Syntax definieren, würde ich eine Linter schreiben (sorry, dieses Modell ist proprietär) Ausschneiden und Einfügen regex ist in dem wird brechen Vermächtnis regex ist und Ausgang „fließend Englisch“ für jemand zu verstehen, besser. Ich würde auch die relative Performance überprüft und Vorschläge für gemeinsame Änderungen hinzuzufügen.

Die kurze Antwort, für mich, das heißt, wenn Sie reguläre Ausdrücke erhalten (oder eine andere Pattern-Matching, die das gleiche tut), die lang genug sind, um ein Problem zu verursachen ... Sie sollten wahrscheinlich in Betracht ziehen, wenn sie sind das richtige Werkzeug für den Job an erster Stelle.

Ehrlich gesagt, jede Fluent Interface scheint, wie es schwieriger sein würde als ein Standard regulärer Ausdruck zu lesen. Für wirklich kurze Ausdrücke, die fließend Version ausführlich, aber nicht zu lange; es ist lesbar. Aber so ist der reguläre Ausdruck für etwas so lange.

Für ein Medium regulären Ausdruck bemessen, eine fließend Schnittstelle wird unhandlich; lange genug, dass es schwer, wenn nicht unmöglich, zu lesen.

Für einen langen regulären Ausdruck (dh der E-Mail-Adresse ein), wo der reguläre Ausdruck tatsächlich schwer ist (wenn nicht unmöglich) zu lesen, wurde die fließend Version unmöglich vor 10 Seiten zu lesen.

Kennen Sie einen ähnlichen Ansatz zu regulären Ausdrücken?

Nein, mit Ausnahme der vorherigen Antwort

Sind Sie damit einverstanden, dass dieser Ansatz könnte besser sein als die Verwendung von einfachen Strings?

Sortieren von - ich glaube, statt einzelner Zeichen Konstrukte darstellen, wir kräftigeren Markup verwenden könnte, aber ich bezweifle es komplexe Logik noch klarer machen würde.

Wie würden Sie die API entwerfen?

Übersetzen jedes Konstrukt in einen Methodennamen und verschachtelte Funktionsaufrufe ermöglichen, so dass es sehr einfach einen String und Ersatzmethodennamen hinein zu nehmen.

Ich denke, die Mehrheit des Wertes bei der Definition eine robuste Bibliothek von Utility-Funktionen, wie matching „E-Mails“, „Telefonnummern“ sein „Linien, die X nicht enthalten“, etc., die individuell angepasst werden können.

würden Sie verwenden, wie ein ordentliches Dienstprogramm in Ihren Projekten?

Vielleicht -. Aber wohl nur für die längeren, wo es leichter zu debuggen Funktionsaufrufen als Debug-String-Bearbeitung würde, oder wo gibt es eine schöne Nutzenfunktion einsatzbereit

Glaubst du, das würde Spaß machen, zu implementieren? ;)

Natürlich!

In Antwort auf den letzten Teil der Frage (für Kudos)

private static final String pattern = "(?:(?:\\r\\n)?[ \\t])*(?:(?:(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t]"
    + ")+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:"
    + "\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:("
    + "?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ "
    + "\\t]))*\"(?:(?:\\r\\n)?[ \\t])*))*@(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\".\\[\\] \\000-\\0"
    + "31]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\"
    + "](?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+"
    + "(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:"
    + "(?:\\r\\n)?[ \\t])*))*|(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z"
    + "|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)"
    + "?[ \\t])*)*\\<(?:(?:\\r\\n)?[ \\t])*(?:@(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\"
    + "r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?["
    + " \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)"
    + "?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t]"
    + ")*))*(?:,@(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?["
    + " \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*"
    + ")(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t]"
    + ")+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*))*)"
    + "*:(?:(?:\\r\\n)?[ \\t])*)?(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+"
    + "|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r"
    + "\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:"
    + "\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t"
    + "]))*\"(?:(?:\\r\\n)?[ \\t])*))*@(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031"
    + "]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\]("
    + "?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?"
    + ":(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?"
    + ":\\r\\n)?[ \\t])*))*\\>(?:(?:\\r\\n)?[ \\t])*)|(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?"
    + ":(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?"
    + "[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*)*:(?:(?:\\r\\n)?[ \\t])*(?:(?:(?:[^()<>@,;:\\\".\\[\\] "
    + "\\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|"
    + "\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>"
    + "@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\""
    + "(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*))*@(?:(?:\\r\\n)?[ \\t]"
    + ")*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\"
    + "\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?"
    + ":[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\["
    + "\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*))*|(?:[^()<>@,;:\\\".\\[\\] \\000-"
    + "\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|("
    + "?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*)*\\<(?:(?:\\r\\n)?[ \\t])*(?:@(?:[^()<>@,;"
    + ":\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\\[(["
    + "^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\""
    + ".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\\[([^\\[\\"
    + "]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*))*(?:,@(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\".\\"
    + "[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\\[([^\\[\\]\\"
    + "r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\".\\[\\] "
    + "\\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]"
    + "|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*))*)*:(?:(?:\\r\\n)?[ \\t])*)?(?:[^()<>@,;:\\\".\\[\\] \\0"
    + "00-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\"
    + ".|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,"
    + ";:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\"(?"
    + ":[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*))*@(?:(?:\\r\\n)?[ \\t])*"
    + "(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\"."
    + "\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:["
    + "^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]"
    + "]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*))*\\>(?:(?:\\r\\n)?[ \\t])*)(?:,\\s*("
    + "?:(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\"
    + "\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:("
    + "?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=["
    + "\\[\"()<>@,;:\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t"
    + "])*))*@(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t"
    + "])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*)(?"
    + ":\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|"
    + "\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*))*|(?:"
    + "[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\"
    + "]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*)*\\<(?:(?:\\r\\n)"
    + "?[ \\t])*(?:@(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\""
    + "()<>@,;:\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)"
    + "?[ \\t])*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>"
    + "@,;:\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*))*(?:,@(?:(?:\\r\\n)?["
    + " \\t])*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,"
    + ";:\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t]"
    + ")*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\"
    + "\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*))*)*:(?:(?:\\r\\n)?[ \\t])*)?"
    + "(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\"."
    + "\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:"
    + "\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\["
    + "\"()<>@,;:\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])"
    + "*))*@(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])"
    + "+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*)(?:\\"
    + ".(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z"
    + "|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*))*\\>(?:("
    + "?:\\r\\n)?[ \\t])*))*)?;\\s*)";

entspricht RFC-konformen E-Mail-Adressen: D

Ein regulärer Ausdruck ist eine Beschreibung eines endlichen Automaten. Die klassische Textdarstellung ist nicht unbedingt schlecht. Es ist kompakt, relativ ohne jeden Zweifel ihre ist, und es ist ziemlich gut angenommen.

Es kann sein, dass eine bessere Darstellung ein Zustandsübergangsdiagramm wäre, aber das wäre wahrscheinlich schwierig sein, im Quellcode zu verwenden.

Eine Möglichkeit, es zu bauen aus einer Vielzahl von Behältern und Kombinierer Objekte wäre.

Etwas entlang der Linie der folgenden (Drehen dies von Pseudo-Code zur Sprache der Wahl für die eifrigen als Übung):

domainlabel = oneormore(characterclass("a-zA-Z0-9-"))
separator = literal(".")
domain = sequence(oneormore(sequence(domainlabel, separator)), domainlabel)
localpart = oneormore(characterclassnot("@"))
emailaddress = sequence(localpart, literal("@"), domain)

Beachten Sie, dass die oben fälschlicherweise arbritarily viele E-Mail-Adressen als gültig klassifizieren, die die Grammatik nicht entsprechen sie erforderlich sind zu folgen, wie die Grammatik mehr erfordert als eine einfache FSM für die vollständige Analyse. Ich glaube nicht, es eine gültige Adresse als ungültig falsch klassifizieren würde, though.

Es sollte entsprechen [^ @] + @ ([a-zA-Z0-9 -] +.) + ([A-zA-Z0-9 -] +).

4. Würden Sie eine solche ordentlich Dienstprogramm in Ihren Projekten verwenden?

Ich würde höchstwahrscheinlich nicht. Ich denke, dass dies ein Fall ist das richtige Werkzeug für den Job zu verwenden. Es gibt einige große Antworten hier wie: 1579202 von Jeremy Stein. Ich habe vor kurzem „bekommen“ reguläre Ausdrücke auf einem aktuellen Projekt und fand sie sehr nützlich sein, wie sie sind, und wenn sie richtig kommentiert sie sind verständlich, wenn man die Syntax kennen.

Ich denke, die „wissen, die Syntax“ Teil ist, was die Menschen aus, um reguläre Ausdrücke dreht, zu denen, die nicht verstehen, sie schauen obskuren und kryptischen, aber sie sind ein mächtiges Werkzeug und in der angewandten Informatik (zB Schreibsoftware für ein lebendiges) ich mag intelligente Profis fühlen sollte und sie lernen können, nutzen und uns angemessen darauf.

Wie sie sagen „Mit großer Macht kommt große Verantwortung.“ Ich habe die Menschen überall reguläre Ausdrücke für alles verwenden gesehen, aber umsichtig von jemandem benutzt, die sich die Zeit genommen hat, um die Syntax gründlich zu lernen, sie sind unglaublich hilfsbereit; zu mir, ihr Zweck, oder zumindest wegnehmen ihre Macht würde in einer Art und Weise der Niederlage eine weitere Ebene hinzugefügt wird.

Dies ist nur meine eigene Meinung und ich kann verstehen, wo die Menschen herkommen, die einen Rahmen, wie dies wünschen würde, oder die reguläre Ausdrücke vermeiden würde, aber ich habe harte Zeit zu hören „Reguläre Ausdrücke sind schlecht“ von denen, die nicht haben die Zeit nehmen, sie zu lernen und eine fundierte Entscheidung zu treffen.

Um all glücklich (regex Meister und Fluidschnittstelle Befürworter), stellen Sie sicher, dass die Fluidschnittstelle ausgeben kann ein geeigneter roher RegexMuster zu machen, und nehmen Sie auch eine regelmäßige regex einer Factory-Methode verwenden und erzeugen Fluid Code für sie.

Was Sie suchen gefunden werden hier: . Es ist ein regulärer Ausdruck buillder, die das Muster Wizard Design follows

Ich hatte vor kurzem diese Idee .

Thought es selbst umzusetzen, aber dann fand ich VerbalExpressions .

Lassen Sie uns vergleichen: Ich habe oft arbeitete mit (N) Hibernate ICriteria Abfragen, die eine in Betracht gezogen werden können Fluent Zuordnung zu SQL. Ich war (und bin immer noch) begeistert von ihnen, aber machten sie die SQL-Abfragen mehr lesbar? Nein, mehr im Gegenteil, aber ein weiterer Vorteil stieg. Es wurde viel einfacher programmatisch Anweisungen, sie zu Unterklasse und erstellen Sie Ihre eigenen Abstraktionen etc

Was ich bin immer an ist, dass für eine bestimmte Sprache eine neue Schnittstelle, wenn es richtig gemacht, sich lohnen kann, aber denken Sie nicht zu sehr davon. In vielen Fällen wird es nicht einfacher geworden (verschachtelte Subtraktion Charakterklassen, Captures in Blick hinter, wenn Verzweigung einige fortgeschrittene Konzepte zu nennen, die fließend schwer zu kombinieren sein wird) zu lesen. Aber in wie vielen Fällen die zusätzlichen Aufwand der Syntax Komplexität die Vorteile einer größeren Flexibilität aufwiegen.

in der Liste der möglichen Alternative hinzuzufügen Ansätze und diese aus dem Zusammenhang zu nehmen von nur Java, die LINQ-Syntax zu betrachten. Hier ist, wie es ist (ein bisschen gekünstelt) aussehen könnte (from, where und select sind Schlüsselwörter in LINQ):

// for ^str(aa|bb){3}
from part in mystring
where part startswith "str"
and part hasgroups "aa" or "bb" as first    /* "aa" or "bb" in group 'first' */
and part repeats first 3                    /* repeat group 'first' 3 times */
select part + "extra"                       /* can contain complete statement block */

nur eine grobe Idee, ich weiß. Die gute Sache von LINQ ist, dass es durch den Compiler, eine Art-von Sprache in einer Sprache geprüft. Standardmäßig LINQ kann auch als fließend gekettet Syntax ausgedrückt werden, die es macht, wenn sie gut gestaltet, kompatibel mit anderen OO-Sprachen.

sage ich gehen für sie, ich bin sicher, dass es Spaß zu implementieren.

Ich schlage vor, ein Abfrage-Modell (ähnlich wie jQuery, django ORM) unter Verwendung, wobei jede Funktion ein Abfrage-Objekt zurückgibt, so können Sie Ketten sie zusammen.

any("a").some("b").one("@").some(chars).one(".").some(chars) //a*b+@\w+\.\w+

Dabei gilt chars vorgegeben beliebiges Zeichen passen.

or kann mit Entscheidungen erreicht werden:

any("a").choice("x", "z") // a(x|z)

Das Argument für jede Funktion kann eine Zeichenfolge oder eine andere Abfrage sein. Zum Beispiel erwähnt die chars Variable oben kann als eine Abfrage definiert werden:

//this one is ascii only
chars = raw("a-zA-Z0-9")

Und so können Sie eine „rohe“ Funktion, die einen regulären Ausdruck Zeichenfolge als Eingabe akzeptiert, wenn es umständlich fühlt sich das fließend Abfragesystem zu verwenden.

Eigentlich können diese Funktionen nur rohe regex zurückkehren, und verketten sie einfach sind, diese rohe reguläre Ausdrücke verketten.

any("a") ---> "a*"
raw("b+") ----> "b+"
one(".") ---> "\."
choice("a", "b") ----> (a|b)

Ich bin nicht sicher, dass mit einem fließend API regexp Ersatz viel bringen würde.

Beachten Sie, dass ich bin kein regexp Assistent (Ich muss wieder lesen der Doc fast jedes Mal, ich brauche einen regulären Ausdruck erstellen).

Ein fließend API würde jedes Medium-Komplexität regexp (sagen wir mal ~ 50 Zeichen) noch komplexer als erforderlich und nicht einfacher am Ende zu lesen, obwohl es die Schöpfung eines regexp verbessern kann in einer IDE, dank Code-Vervollständigung. Aber Code Wartung in der Regel stellt ein höher Kosten als Code-Entwicklung.

In der Tat, ich bin nicht einmal sicher, wäre es möglich, eine API klug genug zu haben, um wirklich genug Führung in den Entwickler bereitzustellen, wenn eine neue regexp zu schaffen, spricht nicht über mehrdeutige Fälle, wie in einer früheren Antwort erwähnt.

Sie haben erwähnt, ein regexp Beispiel für eine RFC. Ich bin 99% sicher (noch 1% Hoffnung ist ;-)), dass jede API nicht, dass beispielsweise jeden einfacher machen würde, aber umgekehrt, dass würde nur macht es komplizierter zu lesen! Das ist ein typisches Beispiel, wo Sie wollen nicht regexp trotzdem verwenden!

Auch in Bezug auf regexp Schöpfung, aufgrund des Problems mehrdeutigen Musters, ist es wahrscheinlich, dass mit einem fließend API, würden Sie nie das erste Mal mit dem richtigen Ausdruck kommen, würden aber mehrmals ändern müssen, bis Sie, was man bekommen wirklich möchten.

Machen Sie keinen Fehler, ich liebe fließend Schnittstellen; Ich habe einige Bibliotheken entwickelt, die sie verwenden, und ich verwende einige 3rd-Party-Bibliotheken basierend auf ihnen (z FEST für Java-Tests). Aber ich glaube nicht, dass sie der goldene Hammer für jedes Problem sein.

Wenn wir Java ausschließlich betrachten, denke ich, das Hauptproblem bei regexps ist die erforderlich Entkommen von Schrägstrichen in Java String-Konstanten. Das ist ein Punkt, dass es unglaublich schwer zu erstellen und verstehen regexp in Java macht. Daher ist der erste Schritt Java Regexp verbessern würde, für mich, eine Sprachumschaltung sein, a la Groovy , wo String-Konstanten müssen nicht umgekehrte Schrägstriche zu entkommen.

Bisher das wäre mein einziger Vorschlag sein regexp in Java zu verbessern.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top