Warum sind reguläre Ausdrücke so umstritten? [geschlossen]

212

Bei der Erforschung regulärer Ausdrücke (auch als RegEx-es bekannt) gibt es viele Personen, die reguläre Ausdrücke als den Heiligen Gral zu betrachten scheinen. Etwas, das so kompliziert aussieht - muss nur die Antwort auf jede Frage sein. Sie neigen dazu zu glauben, dass jedes Problem mit regulären Ausdrücken lösbar ist.

Andererseits gibt es auch viele Menschen, die versuchen, reguläre Ausdrücke um jeden Preis zu vermeiden. Sie versuchen, einen Weg um reguläre Ausdrücke zu finden und zusätzliche Codierung zu akzeptieren, auch wenn reguläre Ausdrücke eine kompaktere Lösung wären.

Warum werden reguläre Ausdrücke als so kontrovers angesehen? Gibt es weit verbreitete Missverständnisse darüber, wie sie funktionieren? Oder könnte es eine breite Überzeugung sein, dass reguläre Ausdrücke im Allgemeinen langsam sind?

Gumbo
quelle
9
Wenn dies eine Diskussion ist, sollte sie dann nicht geschlossen werden? aber ich sehe dort eine echte Frage, also gehört das Diskussionstag vielleicht nicht dazu?
RCIX
6
Im Ernst. Sie sprechen es an und die Leute werden hier verrückt.
Ryan Florence
1
Schöne Beobachtung und Formulierung in der Frage!
imz - Ivan Zakharyaschev
Die Frage ist meinungsbasiert. Die Regel sollte auch hier gelten (oder die Frage sollte bearbeitet werden, um eine genaue Antwort zu erhalten). Das heißt, ich gehe davon aus, dass Regex Controverse von der Ungenauigkeit der Tutorials und Handbücher darüber herrührt. Die meiste Zeit, wenn nicht alle Zeitinformationen gemischt sind und zusätzlich erhalten wir nicht alle Eigenschaften. Wenn Sie diese Sprache nicht verwenden, lernen Sie am Ende etwas, um später zu bemerken, dass es möglicherweise etwas anderes bedeutet. Und schließlich sind Regex-Sonderzeichen nicht auf eine Bedeutung beschränkt, die mehr Verwirrung stiftet.
Intika

Antworten:

136

Ich glaube nicht, dass Leute gegen reguläre Ausdrücke protestieren, weil sie langsam sind, sondern weil sie schwer zu lesen und zu schreiben sind und es schwierig ist, sie richtig zu machen. Während es einige Situationen gibt, in denen reguläre Ausdrücke eine effektive, kompakte Lösung für das Problem darstellen, werden sie manchmal in Situationen eingebettet, in denen es besser ist, stattdessen einen einfach zu lesenden, wartbaren Codeabschnitt zu verwenden.

Kyle Cronin
quelle
2
Und ja, Regexe können im Vergleich zur Verwendung einfacher Funktionen extrem langsam sein. Und nicht nur langsam, sondern die Leistung der Regex-Engine kann bei willkürlichen (vom Benutzer bereitgestellten) Eingaben völlig unvorhersehbar sein .
Pacerier
1
Wenn Sie wissen, wie Regex funktioniert, ist dies überhaupt kein Problem.
Shiplu Mokaddim
8
@ Pacerier, es sind keine langsamen Muster , es sind langsame Motoren . Die meisten (modernen) Engines für reguläre Ausdrücke sind für komplexe Muster (z. B. viele |oder .*) ungeeignet , da sie eine Stack-Maschine und Backtracking verwenden. Aus diesem Grund müssen Sie Ihre regulären Ausdrücke in Perl, Java, Python, Ruby… sorgfältig optimieren. grepZum Beispiel kompilieren Engines für reguläre Ausdrücke im alten Stil ( z. B.) zuerst das Muster zu einem DFA. Danach ist die Komplexität des Musters weitgehend irrelevant. Ich habe gerade Java und grep für den gleichen Text und das gleiche Muster verwendet: 22min vs 2s. Hier ist die Wissenschaft: swtch.com/~rsc/regexp/regexp1.html
Hagello
122

Regexes wartbar machen

Ein wichtiger Fortschritt bei der Entmystifizierung der Muster, die zuvor als „reguläre Ausdrücke“ bezeichnet wurden, ist Perls /xRegex-Flag, das manchmal (?x)beim Einbetten geschrieben wird und Leerzeichen (Zeilenumbruch, Einrücken) und Kommentare zulässt. Dies verbessert die Lesbarkeit und damit die Wartbarkeit erheblich. Der Leerraum ermöglicht kognitives Chunking, sodass Sie sehen können, welche Gruppen mit welchen Gruppen verbunden sind.

Moderne Muster unterstützen jetzt auch relativ nummerierte und benannte Rückreferenzen. Das bedeutet, dass Sie keine Erfassungsgruppen mehr zählen müssen, um herauszufinden, ob Sie $4oder benötigen \7. Dies hilft beim Erstellen von Mustern, die in weitere Muster aufgenommen werden können.

Hier ist ein Beispiel für eine relativ nummerierte Erfassungsgruppe:

$ dupword = qr {\ b (?: (\ w +) (?: \ s + \ g {-1}) +) \ b} xi;
$ quote = qr {(["']) $ dupword \ 1} x;

Und hier ist ein Beispiel für den überlegenen Ansatz benannter Captures:

$dupword = qr{ \b (?: (?<word> \w+ ) (?: \s+ \k<word> )+ ) \b }xi;
$quoted  = qr{ (?<quote> ["'] ) $dupword  \g{quote} }x;

Grammatische Regexe

Das Beste ist , dass diese benannten Captures in einem (?(DEFINE)...)Block platziert werden können, sodass Sie die Deklaration von der Ausführung einzelner benannter Elemente Ihrer Muster trennen können. Dadurch verhalten sie sich eher wie Unterprogramme innerhalb des Musters.
Ein gutes Beispiel für diese Art von „grammatikalischem Regex“ finden Sie in dieser und dieser Antwort . Diese sehen viel eher wie eine grammatikalische Erklärung aus.

Wie letzterer Sie erinnert:

… Stellen Sie sicher, dass Sie niemals Linienrauschmuster schreiben. Sie müssen nicht und Sie sollten nicht. Es kann keine Programmiersprache gewartet werden, die Leerzeichen, Kommentare, Unterprogramme oder alphanumerische Bezeichner verbietet. Verwenden Sie also all diese Dinge in Ihren Mustern.

Dies kann nicht überbetont werden. Wenn Sie diese Dinge nicht in Ihren Mustern verwenden, werden Sie natürlich oft einen Albtraum schaffen. Aber wenn Sie sie verwenden, brauchen Sie nicht.

Hier ist ein weiteres Beispiel für ein modernes grammatikalisches Muster, das zum Parsen von RFC 5322 verwendet wird: use 5.10.0;

$rfc5322 = qr{

   (?(DEFINE)

     (?<address>         (?&mailbox) | (?&group))
     (?<mailbox>         (?&name_addr) | (?&addr_spec))
     (?<name_addr>       (?&display_name)? (?&angle_addr))
     (?<angle_addr>      (?&CFWS)? < (?&addr_spec) > (?&CFWS)?)
     (?<group>           (?&display_name) : (?:(?&mailbox_list) | (?&CFWS))? ; (?&CFWS)?)
     (?<display_name>    (?&phrase))
     (?<mailbox_list>    (?&mailbox) (?: , (?&mailbox))*)

     (?<addr_spec>       (?&local_part) \@ (?&domain))
     (?<local_part>      (?&dot_atom) | (?&quoted_string))
     (?<domain>          (?&dot_atom) | (?&domain_literal))
     (?<domain_literal>  (?&CFWS)? \[ (?: (?&FWS)? (?&dcontent))* (?&FWS)?
                                   \] (?&CFWS)?)
     (?<dcontent>        (?&dtext) | (?&quoted_pair))
     (?<dtext>           (?&NO_WS_CTL) | [\x21-\x5a\x5e-\x7e])

     (?<atext>           (?&ALPHA) | (?&DIGIT) | [!#\$%&'*+-/=?^_`{|}~])
     (?<atom>            (?&CFWS)? (?&atext)+ (?&CFWS)?)
     (?<dot_atom>        (?&CFWS)? (?&dot_atom_text) (?&CFWS)?)
     (?<dot_atom_text>   (?&atext)+ (?: \. (?&atext)+)*)

     (?<text>            [\x01-\x09\x0b\x0c\x0e-\x7f])
     (?<quoted_pair>     \\ (?&text))

     (?<qtext>           (?&NO_WS_CTL) | [\x21\x23-\x5b\x5d-\x7e])
     (?<qcontent>        (?&qtext) | (?&quoted_pair))
     (?<quoted_string>   (?&CFWS)? (?&DQUOTE) (?:(?&FWS)? (?&qcontent))*
                          (?&FWS)? (?&DQUOTE) (?&CFWS)?)

     (?<word>            (?&atom) | (?&quoted_string))
     (?<phrase>          (?&word)+)

     # Folding white space
     (?<FWS>             (?: (?&WSP)* (?&CRLF))? (?&WSP)+)
     (?<ctext>           (?&NO_WS_CTL) | [\x21-\x27\x2a-\x5b\x5d-\x7e])
     (?<ccontent>        (?&ctext) | (?&quoted_pair) | (?&comment))
     (?<comment>         \( (?: (?&FWS)? (?&ccontent))* (?&FWS)? \) )
     (?<CFWS>            (?: (?&FWS)? (?&comment))*
                         (?: (?:(?&FWS)? (?&comment)) | (?&FWS)))

     # No whitespace control
     (?<NO_WS_CTL>       [\x01-\x08\x0b\x0c\x0e-\x1f\x7f])

     (?<ALPHA>           [A-Za-z])
     (?<DIGIT>           [0-9])
     (?<CRLF>            \x0d \x0a)
     (?<DQUOTE>          ")
     (?<WSP>             [\x20\x09])
   )

   (?&address)

}x;

Ist das nicht bemerkenswert - und großartig? Sie können eine Grammatik im BNF-Stil direkt in Code übersetzen, ohne ihre grundlegende Struktur zu verlieren!

Wenn Ihnen moderne grammatikalische Muster immer noch nicht ausreichen, bietet das brillante Regexp::GrammarsModul von Damian Conway eine noch sauberere Syntax mit überlegenem Debugging. Hier ist derselbe Code zum Parsen der Neufassung von RFC 5322 in ein Muster aus diesem Modul:

#!/usr/bin/perl

use strict;
use warnings;
use 5.010;
use Data::Dumper "Dumper";

my $rfc5322 = do {
    use Regexp::Grammars;    # ...the magic is lexically scoped
    qr{

    # Keep the big stick handy, just in case...
    # <debug:on>

    # Match this...
    <address>

    # As defined by these...
    <token: address>         <mailbox> | <group>
    <token: mailbox>         <name_addr> | <addr_spec>
    <token: name_addr>       <display_name>? <angle_addr>
    <token: angle_addr>      <CFWS>? \< <addr_spec> \> <CFWS>?
    <token: group>           <display_name> : (?:<mailbox_list> | <CFWS>)? ; <CFWS>?
    <token: display_name>    <phrase>
    <token: mailbox_list>    <[mailbox]> ** (,)

    <token: addr_spec>       <local_part> \@ <domain>
    <token: local_part>      <dot_atom> | <quoted_string>
    <token: domain>          <dot_atom> | <domain_literal>
    <token: domain_literal>  <CFWS>? \[ (?: <FWS>? <[dcontent]>)* <FWS>?

    <token: dcontent>        <dtext> | <quoted_pair>
    <token: dtext>           <.NO_WS_CTL> | [\x21-\x5a\x5e-\x7e]

    <token: atext>           <.ALPHA> | <.DIGIT> | [!#\$%&'*+-/=?^_`{|}~]
    <token: atom>            <.CFWS>? <.atext>+ <.CFWS>?
    <token: dot_atom>        <.CFWS>? <.dot_atom_text> <.CFWS>?
    <token: dot_atom>        <.CFWS>? <.dot_atom_text> <.CFWS>?
    <token: dot_atom_text>   <.atext>+ (?: \. <.atext>+)*

    <token: text>            [\x01-\x09\x0b\x0c\x0e-\x7f]
    <token: quoted_pair>     \\ <.text>

    <token: qtext>           <.NO_WS_CTL> | [\x21\x23-\x5b\x5d-\x7e]
    <token: qcontent>        <.qtext> | <.quoted_pair>
    <token: quoted_string>   <.CFWS>? <.DQUOTE> (?:<.FWS>? <.qcontent>)*
                             <.FWS>? <.DQUOTE> <.CFWS>?

    <token: word>            <.atom> | <.quoted_string>
    <token: phrase>          <.word>+

    # Folding white space
    <token: FWS>             (?: <.WSP>* <.CRLF>)? <.WSP>+
    <token: ctext>           <.NO_WS_CTL> | [\x21-\x27\x2a-\x5b\x5d-\x7e]
    <token: ccontent>        <.ctext> | <.quoted_pair> | <.comment>
    <token: comment>         \( (?: <.FWS>? <.ccontent>)* <.FWS>? \)
    <token: CFWS>            (?: <.FWS>? <.comment>)*
                             (?: (?:<.FWS>? <.comment>) | <.FWS>)

    # No whitespace control
    <token: NO_WS_CTL>       [\x01-\x08\x0b\x0c\x0e-\x1f\x7f]

    <token: ALPHA>           [A-Za-z]
    <token: DIGIT>           [0-9]
    <token: CRLF>            \x0d \x0a
    <token: DQUOTE>          "
    <token: WSP>             [\x20\x09]

    }x;

};


while (my $input = <>) {
    if ($input =~ $rfc5322) {
        say Dumper \%/;       # ...the parse tree of any successful match
                              # appears in this punctuation variable
    }
}

Es gibt viele gute Dinge auf der Perlre- Manpage , aber diese dramatischen Verbesserungen der grundlegenden Regex- Designfunktionen sind keineswegs nur auf Perl beschränkt. In der Tat ist die Manpage zu pcrepattern möglicherweise leichter zu lesen und deckt dasselbe Gebiet ab.

Moderne Muster haben fast nichts mit den primitiven Dingen zu tun, die Ihnen in Ihrer Klasse für endliche Automaten beigebracht wurden.

tchrist
quelle
9
JA! JA! Schließlich zeigt jemand ein großartiges Beispiel dafür, wie lesbar Regexes mit dem Modifikator x sein können. Ich kann nicht glauben, wie wenige Menschen wissen, dass es existiert, geschweige denn, dass sie es tatsächlich benutzen.
Shabbyrobe
1
@ Shabbyrobe: Es ist nicht nur /x. Es ist die grammatikalische Verwendung der Regexes mit (?&name)internen Regex-Subroutinen, die dies wirklich zum Leuchten bringt.
Tchrist
+1 Du lernst immer etwas Neues. Ich wusste nicht, dass PCRE eine "falsche" Bedingung für Definitionen hat.
NikiC
5
Python hat ebenfalls eine re.VERBOSEFlagge.
Mechanische Schnecke
3
Gehen Sie einfach voran und sagen Sie, dass ich immer noch erstaunt bin, wie lange die Leute gehen werden, um Regex nutzbar zu machen.
Slater Victoroff
68

Regexes sind ein großartiges Werkzeug, aber die Leute denken: "Hey, was für ein großartiges Werkzeug, ich werde es verwenden, um X zu machen!" Dabei ist X etwas, für das ein anderes Tool besser ist (normalerweise ein Parser). Es ist der Standard mit einem Hammer, bei dem Sie ein Problem mit dem Schraubendreher benötigen.

Chas. Owens
quelle
4
Denken Sie daran, dass die meisten Parser - komplexe Analysatoren - immer noch reguläre Ausdrücke verwenden, um ihre Daten zu analysieren :-)
Jasper Bekkers
62
Zu sagen, dass Parser reguläre Ausdrücke verwenden, ist wie zu sagen, dass Parser Zuweisungsanweisungen verwenden. Es bedeutet nichts, bis Sie sehen, wie sie verwendet werden.
Chas. Owens
24
Die Verwendung eines RegEx, wenn ein Parser besser ist, ist ärgerlich. Die Verwendung eines RegEx, wenn die Standardfunktionen zum Suchen oder Ersetzen von Zeichenfolgen in der Sprache funktionieren (und normalerweise in linearer Zeit), ist einfach unverzeihlich.
jmucchiello
1
Einverstanden, da ein RegEx ein Alleskönner sein muss, ist sein Verarbeitungsaufwand enorm. Nur weil die Verwendung einer RegEx-Engine einfach erscheint, bedeutet dies nicht, dass sie eine bessere Lösung als ein iterativer Parser ist (entwicklerabhängiger Schwellenwert). Eines meiner Lieblingsbeispiele für PHPs split($pattern,$string)vs explode($delimiter,$string)- zum Glück wird das erstere abgeschrieben, aber viele Codes verwendeten das erstere, wenn sie nur die Leistung des späteren benötigten. Einverstanden, RegEx bieten ein einfaches Werkzeug, um einige Dinge zu tun, aber wenn Sie nicht die volle Kraft der regulären Ausdrücke benötigen, sie
Rudu
4
Lexikalische Analysegeräte können tatsächlich reguläre Ausdrücke verwenden. Sie werden auch als Tokenizer bezeichnet, sind jedoch keine syntaktischen Analysatoren (oder Parser). Um eine ausreichend komplizierte Zeichenfolge zu lesen, sollte ein Tokenizer verwendet werden, um die Zeichenfolge als Token zu lesen (möglicherweise mit regulären Ausdrücken, möglicherweise nicht, abhängig vom Tokenizer). Diese Token sollten dann an den Parser übergeben werden, der sie mit Grammatikregeln verarbeitet, die definitiv keine regulären Ausdrücke sind.
Axel
53

Fast jeder, den ich kenne, der regelmäßig reguläre Ausdrücke verwendet (Wortspiel beabsichtigt), hat einen Unix-Hintergrund, in dem er Tools verwendet, die REs als erstklassige Programmierkonstrukte wie grep, sed, awk und Perl behandeln. Da es fast keinen syntaktischen Aufwand gibt, einen regulären Ausdruck zu verwenden, steigt ihre Produktivität, wenn sie dies tun.

Im Gegensatz dazu neigen Programmierer, die Sprachen verwenden, in denen REs eine externe Bibliothek sind, dazu, nicht zu berücksichtigen, was reguläre Ausdrücke auf den Tisch bringen können. Die "Zeitkosten" des Programmierers sind so hoch, dass entweder a) REs nie als Teil ihrer Ausbildung erschienen sind oder b) sie nicht in REs "denken" und lieber auf bekanntere Muster zurückgreifen.

Barry Brown
quelle
11
Ja, ich habe Python nie vergeben, dass er die Regex-Syntax mithilfe einer Bibliothek ausführlich formuliert hat. Ich denke, es ist Reinheit über Vernunft.
Slikts
7
Ich komme aus einem Unix-Hintergrund, habe sed-, awk- und perl-Ladevorgänge verwendet und natürlich viel gepackt, aber ich weiß, dass es sich bei der Verwendung eines regulären Ausdrucks um einen Nur-Schreib-Hack handelt, den ich nicht gerne pflege. Es ist gut für Shell-Skripte / One-Timer, aber für echte Arbeit, für alles, was nicht nur zum Speichern von Daten dient, verwende ich jetzt einen geeigneten Tokenizer / Lexer / Parser mit klarer Syntax. Mein Favorit macht alles / jeden, sauber + kann sich selbst optimieren. Ich habe auf die harte Tour gelernt und über viele Jahre hinweg, dass ein bisschen Selbstdisziplin am Anfang später weniger Aufwand bedeutet. Ein Regex ist ein Moment auf der Tastatur und ein Leben lang auf der Stirn.
AndrewC
44

Mit regulären Ausdrücken können Sie eine benutzerdefinierte Finite-State-Machine (FSM) auf kompakte Weise schreiben, um eine Eingabezeichenfolge zu verarbeiten. Es gibt mindestens zwei Gründe, warum die Verwendung regulärer Ausdrücke schwierig ist:

  • Die Softwareentwicklung der alten Schule erfordert viel Planung, Papiermodelle und sorgfältige Überlegungen. Reguläre Ausdrücke passen sehr gut in dieses Modell, denn um einen effektiven Ausdruck richtig zu schreiben, muss man viel darauf starren und die Pfade des FSM visualisieren.

    Moderne Softwareentwickler würden viel lieber Code ausarbeiten und einen Debugger verwenden, um die Ausführung zu durchlaufen und festzustellen, ob der Code korrekt ist. Reguläre Ausdrücke unterstützen diesen Arbeitsstil nicht sehr gut. Ein "Lauf" eines regulären Ausdrucks ist effektiv eine atomare Operation. Es ist schwierig, die schrittweise Ausführung in einem Debugger zu beobachten.

  • Es ist zu einfach, einen regulären Ausdruck zu schreiben, der versehentlich mehr Eingaben akzeptiert, als Sie beabsichtigen. Der Wert eines regulären Ausdrucks stimmt nicht wirklich mit gültigen Eingaben überein, sondern mit ungültigen Eingaben . Techniken, um "negative Tests" für reguläre Ausdrücke durchzuführen, sind nicht sehr fortgeschritten oder zumindest nicht weit verbreitet.

    Dies führt dazu, dass reguläre Ausdrücke schwer zu lesen sind. Wenn Sie nur einen regulären Ausdruck betrachten, ist viel Konzentration erforderlich, um alle möglichen Eingaben zu visualisieren, die abgelehnt werden sollten, aber fälschlicherweise akzeptiert werden. Haben Sie jemals versucht, den regulären Ausdruckscode eines anderen zu debuggen ?

Wenn es heute bei Softwareentwicklern einen Widerstand gegen die Verwendung regulärer Ausdrücke gibt, liegt dies meiner Meinung nach hauptsächlich an diesen beiden Faktoren.

Bill Karwin
quelle
4
Es gibt ausgezeichnete Tools zum Debuggen von Regexps: regexbuddy.com
Jasper Bekkers
15
perl -Mre = debug -e "q [aabbcc] = ~ / ab * [cd] /"
Brad Gilbert
15
Ich glaube nicht, dass ich jemals das Akronym "FSM" sehen kann, ohne an das fliegende Spaghetti-Monster zu denken.
Shabbyrobe
4
@ Shabbyrobe: Ich will nicht beleidigen. Wenn Sie möchten, können Sie den deterministischen endlichen Automaten (DFA) verwenden.
Bill Karwin
37

Die Leute neigen dazu, reguläre Ausdrücke für schwierig zu halten. aber das liegt daran, dass sie sie falsch verwenden. Schreiben komplexer Einzeiler ohne Kommentare, Einrückungen oder benannte Captures. (Sie stopfen Ihren komplexen SQL-Ausdruck nicht in einer Zeile ohne Kommentare, Einrückungen oder Aliase, oder?) Also ja, für viele Leute machen sie keinen Sinn.

Wenn Ihr Job jedoch etwas mit dem Parsen von Text zu tun hat (ungefähr jede Webanwendung da draußen ...) und Sie keinen regulären Ausdruck kennen, saugen Sie an Ihrem Job und verschwenden Ihre eigene Zeit und die Ihrer Arbeitgeber. Es gibt ausgezeichnete Ressourcen , die Ihnen alles über sie beibringen, was Sie jemals wissen müssen, und vieles mehr.

Jasper Bekkers
quelle
2
Nun ... der Unterschied ist, dass mehrere Leerzeichen in Regex eine Bedeutung haben, in anderen Sprachen jedoch nicht. Deshalb sind sie normalerweise Einzeiler (die manchmal in mehrere Zeilen eingeschlossen sind :)
Rado
14
@Rado: Perl hat zum Beispiel den xModifikator für reguläre Ausdrücke, der bewirkt, dass Leerzeichen ignoriert werden. Auf diese Weise können Sie den regulären Ausdruck in einige Zeilen einfügen und Kommentare hinzufügen.
Nathan Fellman
9
Ebenso hat Python re.Xaka re.VERBOSE.
Craig McQueen
2
Ebenso der xModifikator in tcl. Ich glaube, es ist ziemlich Standard, da tcl im Gegensatz zu anderen Sprachen kein PCRE verwendet.
Slebetman
2
@AndrewC Das ist eine der gröbsten Fehlinterpretationen, die dieser Beitrag hätte bekommen können.
Jasper Bekkers
28

Weil ihnen das beliebteste Lernwerkzeug in den allgemein akzeptierten IDEs fehlt: Es gibt keinen Regex-Assistenten. Nicht einmal Autocompletion. Sie müssen das Ganze ganz alleine codieren.

dkretz
quelle
3
Dann verwenden Sie die falsche IDE ... Sogar mein Texteditor bietet Regex-Hinweise.
CurtainDog
1
Nebenbei bemerkt sind Expresso und The Regex Coach sehr nützliche Werkzeuge zum Erstellen regulärer Ausdrücke.
Mun
22
Wie um alles in der Welt würden Sie einen regulären Ausdruck automatisch vervollständigen?
AmbroseChapel
3
EditPad Pro hat eine Syntaxhervorhebung für reguläre Ausdrücke im Suchfeld, aber ich finde es eher ärgerlich als hilfreich und lasse es ausgeschaltet. Aber ich weiß es zu schätzen, wenn ich weiß, wann ich unübertroffene Klammern habe. Insbesondere Klammern können ein Bär sein, den man im Auge behalten muss.
Alan Moore
2
@ AmbroseChapel - Ich bin ein paar Jahre zu spät zu dieser Diskussion. Aber ich habe unter regexhero.net/tester einen Mechanismus zur automatischen Vervollständigung erstellt. Er wird durch die gängigen Konstrukte in runden (), quadratischen []oder geschweiften {}Klammern initiiert . Es wird auch aus dem Backslash heraus funktionieren.
Steve Wortham
17

" Reguläre Ausdrücke: Jetzt haben Sie zwei Probleme " ist ein großartiger Artikel von Jeff Atwood zu diesem Thema. Grundsätzlich sind reguläre Ausdrücke "schwer"! Sie können neue Probleme verursachen. Sie sind jedoch wirksam.

Anthony
quelle
16

Ich denke nicht, dass sie so kontrovers sind.

Ich denke auch, dass Sie Ihre eigene Frage irgendwie beantwortet haben, weil Sie darauf hinweisen, wie dumm es wäre, sie überall zu verwenden ( nicht alles ist eine reguläre Sprache 2 ) oder sie überhaupt nicht zu verwenden. Sie als Programmierer müssen eine intelligente Entscheidung treffen, wann reguläre Ausdrücke dem Code helfen oder ihn verletzen. Bei einer solchen Entscheidung sind zwei wichtige Dinge zu beachten: Wartbarkeit (was Lesbarkeit impliziert) und Erweiterbarkeit.

Für diejenigen, die ihnen besonders abgeneigt sind, ist meine Vermutung, dass sie nie gelernt haben, sie richtig zu benutzen. Ich denke, die meisten Leute, die nur ein paar Stunden mit einem anständigen Tutorial verbringen, werden sie herausfinden und sehr schnell fließend werden. Hier ist mein Vorschlag, wo ich anfangen soll:

http://docs.python.org/howto/regex

Obwohl diese Seite über reguläre Ausdrücke im Kontext von Python spricht, habe ich festgestellt, dass die Informationen an anderer Stelle sehr zutreffend sind. Es gibt einige Dinge, die Python-spezifisch sind, aber ich glaube, sie sind klar vermerkt und leicht zu merken.

allyourcode
quelle
2
Die Seite scheint zu docs.python.org/howto/regex
Dominic K
@ DMan Danke. Ich werde meine Antwort bearbeiten, um sie zu reflektieren.
Allyourcode
11

Reguläre Ausdrücke sind Zeichenfolgen, was arithmetische Operatoren für Zahlen sind, und ich würde sie nicht als kontrovers betrachten. Ich denke, dass selbst ein ziemlich millitanter OO- Aktivist wie ich (der dazu neigt, andere Objekte gegenüber Strings zu wählen) es schwer haben würde, sie abzulehnen.

Peter Mortensen
quelle
7

Das Problem ist, dass Regexe möglicherweise so mächtig sind, dass Sie Dinge damit tun können, für die Sie etwas anderes verwenden sollten.

Ein guter Programmierer sollte wissen, wo er sie verwenden soll und wo nicht. Das typische Beispiel ist das Parsen nicht regulärer Sprachen (siehe Entscheiden, ob eine Sprache regulär ist ).

Ich denke, dass Sie nichts falsch machen können, wenn Sie sich zunächst auf echte reguläre Ausdrücke beschränken (keine Erweiterungen). Einige Erweiterungen können Ihr Leben ein bisschen einfacher machen, aber wenn Sie etwas finden, das schwer als echte Regex auszudrücken ist , kann dies ein Hinweis darauf sein, dass eine Regex nicht das richtige Werkzeug ist.

Svante
quelle
5

Sie können fast genauso gut fragen, warum Goto umstritten sind.

Wenn Sie so viel "offensichtliche" Macht erhalten, neigen die Leute dazu, sie für Situationen zu missbrauchen, für die sie nicht die beste Option sind. Die Anzahl der Personen, die beispielsweise CSVs oder XML oder HTML in regulären Ausdrücken analysieren möchten, überrascht mich. Es ist das falsche Werkzeug für den Job. Einige Benutzer bestehen jedoch trotzdem darauf, reguläre Ausdrücke zu verwenden.

Persönlich versuche ich, dieses glückliche Medium zu finden - verwende Regexe für das, wofür sie gut sind, und vermeide sie, wenn sie nicht optimal sind.

Beachten Sie, dass Regexe weiterhin zum Parsen von CSVs, XML, HTML usw. verwendet werden können. In der Regel jedoch nicht in einer einzelnen Regex.

Tanktalus
quelle
Sicher können Sie jedes dieser Formate in einem einzigen regulären Ausdruck analysieren, das ist die Kraft von regulären Ausdrücken, Baby! Ob Sie das tun wollen oder nicht, ist eine ganz andere Sache.
Jasper
4

Ich denke nicht, dass "kontrovers" das richtige Wort ist.

Aber ich habe unzählige Beispiele gesehen, in denen Leute sagen: "Was ist der reguläre Ausdruck, den ich brauche, um so und so eine String-Manipulation durchzuführen?" Welches sind XY Probleme.

Mit anderen Worten, sie sind von der Annahme ausgegangen, dass eine Regex das ist, was sie brauchen, aber sie wären besser dran mit einem split (), einer Übersetzung wie perls tr ///, bei der die Zeichen durch die anderen ersetzt werden, oder nur ein Index ().

AmbroseChapel
quelle
4

Dies ist ein interessantes Thema.
Viele Regexp- Liebhaber scheinen die Prägnanz der Formel mit Effizienz zu verwechseln.
Darüber hinaus erzeugt ein regulärer Ausdruck, der viel Nachdenken erfordert, für den Autor eine massive Befriedigung, die ihn sofort legitimiert.

Aber ... reguläre Ausdrücke sind so praktisch, wenn die Leistung kein Problem darstellt und Sie schnell mit einer Textausgabe umgehen müssen, beispielsweise in Perl. Auch während der Leistung ist ein Problem kann man es vorziehen , nicht zu versuchen , die regexp - Bibliothek zu schlagen , indem einen selbstgemachten Algorithmus, fehlerhaft sein kann oder weniger effizient.

Daneben gibt es eine Reihe von Gründen, aus denen Regexps beispielsweise zu Unrecht kritisiert werden

  • Der reguläre Ausdruck ist nicht effizient, da es nicht offensichtlich ist, den obersten zu erstellen
  • Einige Programmierer "vergessen", nur einmal einen regulären Ausdruck zu kompilieren, der oft verwendet werden soll (wie ein statisches Muster in Java).
  • Einige Programmierer entscheiden sich für die Trial-and-Error- Strategie - funktioniert noch weniger mit regulären Ausdrücken!
e2-e4
quelle
4

Was ich denke ist, dass das Lernen von Regex und das Aufrechterhalten von Regex unpopulär ist. Die meisten Entwickler sind faul oder die meisten verlassen sich auf externe Bibliotheken, um die Analyse für sie durchzuführen. Sie verlassen sich auf Google, um die Antwort zu erhalten, und fragen sogar in Foren nach der vollständige Code für ihr Problem. Aber wenn es darum geht, einen regulären Ausdruck zu implementieren oder zu ändern / zu pflegen, schlagen sie einfach fehl.

Es gibt ein beliebtes Sprichwort: "Freunde lassen Freunde Regex nicht zum Parsen von HTML verwenden."

Aber was mich betrifft, habe ich mit Regex vollständige HTML-Parser erstellt, und ich finde, dass Regex HTML-Zeichenfolgen sowohl in Bezug auf die Geschwindigkeit als auch in Bezug auf den Speicher besser analysieren kann (wenn Sie eine Idee haben, was Sie erreichen sollen :)).

Rajeev
quelle
2
Ich finde es unaufrichtig, die meisten Entwickler abzuschreiben ... als faul. Ich würde sagen, dass die Syntax für Uninitiierte sehr kryptisch, nicht intuitiv und voller Fallstricke ist, was zu einer hohen Eintrittsbarriere führt. Aus dem gleichen Grund hat Perl für viele einen "schlechten" Ruf, ist aber auch eine sehr mächtige Sprache. Es ist, als würde man versuchen, mathematische Ausdrücke zu lesen, bevor man die Symbole kennt. Es ist entmutigend und Entwickler müssen mit ihrer Zeit juristisch umgehen, um zu wissen, dass sie Vorteile für das Erlernen dieser Syntax erhalten.
Katastic Voyage
Sie werden Randfälle in HTML vermissen, da HTML keine reguläre Sprache ist. Sie sind sicher, wenn Sie beabsichtigen, eine bekannte Teilmenge von HTML
Boyang
2

Reguläre Ausdrücke sind für viele Menschen, auch für mich, ein ernstes Rätsel. Es funktioniert großartig, aber es ist wie das Betrachten einer mathematischen Gleichung. Ich freue mich, Ihnen mitteilen zu können, dass jemand unter http://regexlib.com/ endlich einen konsolidierten Speicherort für verschiedene Funktionen für reguläre Ausdrücke erstellt hat . Wenn Microsoft jetzt nur eine Klasse für reguläre Ausdrücke erstellen würde, die automatisch einen Großteil der gängigen Aufgaben wie das Entfernen von Buchstaben oder das Filtern von Datumsangaben erledigt.

Al Katawazi
quelle
2
Sie verpassen den Punkt. Die Idee von Regexen ist, dass Sie einige Zeit in das Erlernen investieren und wenn Sie fertig sind, brauchen Sie keine magische "Read a Date" -Klasse mehr. Stattdessen ist für sie nur sehr wenig Aufwand erforderlich. Darüber hinaus ist das Schreiben eines für ein "JJJJ / MM / TT" genauso wenig erforderlich wie das Schreiben eines für "MM-TT-JJJJ" oder sogar eines für "MM-JJJJ / TT" (das gewonnen hat) kommt nicht oft vor, aber es ist ein Beispiel dafür, wie man Dinge tun kann, die eine magische Klasse niemals kann ").
Jasper
1

Ich finde reguläre Ausdrücke manchmal von unschätzbarem Wert. Wenn ich einige "unscharfe" Suchen durchführen muss und diese möglicherweise ersetzen muss. Wenn Daten variieren können und eine gewisse Zufälligkeit haben. Wenn ich jedoch einfach suchen und ersetzen oder nach einer Zeichenfolge suchen muss, verwende ich keine regulären Ausdrücke. Obwohl ich viele Leute kenne, die das tun, benutzen sie es für alles. Das ist die Kontroverse.

Wenn Sie einen Stift in die Wand stecken möchten, verwenden Sie keinen Hammer. Ja, es wird funktionieren, aber wenn Sie den Hammer bekommen, könnte ich 20 Reißnägel in die Wand stecken.

Reguläre Ausdrücke sollten für das verwendet werden, wofür sie entwickelt wurden, und nicht weniger.

Brent Baisley
quelle
0

Während ich denke, dass Regexes ein wesentliches Werkzeug sind, ist das Ärgerlichste an ihnen, dass es verschiedene Implementierungen gibt. Geringe Unterschiede in der Syntax, den Modifikatoren und insbesondere in der "Gier" können die Dinge wirklich chaotisch machen, was Versuch und Irrtum erfordert und manchmal rätselhafte Fehler erzeugt.

ndr
quelle
Wie unterscheiden sich Regex-Implementierungen in ihrem Ansatz zur maximalen Übereinstimmung, was Sie meiner Meinung nach "Gier" nennen? Meinen Sie damit den Unterschied zwischen ganz links längsten im Vergleich längsten ganz links Semantik? Das ist der einzige Unterschied, den ich kenne. dh ob Gier Trumpf Eifer ist oder umgekehrt .
Tchrist
0

In einigen Fällen denke ich, dass Sie sie verwenden müssen. Zum Beispiel, um einen Lexer zu bauen.

Meiner Meinung nach ist dies eine Sichtweise von Menschen, die Regexp schreiben können, und von Menschen, die dies nicht (oder kaum) tun. Ich persönlich denke, dies ist ein guter Gedanke, um beispielsweise die Eingabe eines Formulars zu überprüfen, sei es in Javascript, um den Benutzer zu warnen, oder in serverseitiger Sprache.

Aif
quelle
0

Ich denke, es ist eine weniger bekannte Technik unter Programmierern. Es gibt also keine breite Akzeptanz dafür. Und wenn Sie einen nicht-technischen Manager haben, der Ihren Code oder Ihre Arbeit überprüft, ist ein regulärer Ausdruck sehr schlecht. Sie werden Stunden damit verbringen, einen perfekten regulären Ausdruck zu schreiben, und Sie werden einige Punkte für das Modul erhalten, wenn Sie glauben, dass er / sie so wenige Codezeilen geschrieben hat. Wie bereits an anderer Stelle erwähnt, ist das Lesen regulärer Ausdrücke eine sehr schwierige Aufgabe.

Satya Prakash
quelle
1
Das Lesen regulärer Ausdrücke ist nur dann eine schwierige Aufgabe, wenn der Programmierer, der sie erstellt hat, keine Leerzeichen, Kommentare, alphanumerischen Bezeichner und möglicherweise auch eingebettete Unterprogramme über eine verzögerte Ausführung verwendet hat. Kurz gesagt, alle für die allgemeine Programmierung geltenden Softwareentwicklungstechniken sollten auch in regulären Ausdrücken befolgt werden. Wenn diese Prinzipien ignoriert werden, erstellt der Autor keinen professionellen Code.
Tchrist
Ich denke, Ihr Manager weiß nicht, dass "der wahre Held der Programmierung derjenige ist, der negativen Code schreibt."
Rajeev
Wenn Ihr Manager Sie für die Ausführung des Auftrags mit 3 Codezeilen (einschließlich regulärer Ausdrücke) anstößt, während er einen Doofus-Mitarbeiter lobt, der dies in 900 Zeilen Assembler getan hat ... Ich schlage vor, einen neuen Auftrag zu finden.
Phil Perry
0

Anständige Systeme für reguläre Ausdrücke, wie sie in Lex und Yacc für die Compilerdefinition verwendet werden, sind gut, sehr nützlich und sauber. In diesen Systemen werden Ausdruckstypen in Bezug auf andere definiert. Es sind die abscheulichen, missgebildeten, unlesbaren, einzeiligen regulären Ausdrücke mit Zeilenrauschen, die häufig in Perl- und Sed-Code (usw.) vorkommen und „umstritten“ sind (Müll).

Sam Watkins
quelle
-4

Die beste gültige und normale Verwendung für Regex ist die Validierung des E-Mail-Adressformats.

Das ist eine gute Anwendung davon.

Ich habe unzählige Male reguläre Ausdrücke als Unikate in TextPad verwendet, um flache Dateien zu massieren, CSV-Dateien zu erstellen, SQL-Einfügeanweisungen zu erstellen und dergleichen.

Gut geschriebene reguläre Ausdrücke sollten nicht zu langsam sein. Normalerweise sind die Alternativen, wie z. B. Tonnen von Anrufen zum Ersetzen, weitaus langsamere Optionen. Könnte es auch in einem Durchgang tun.

Viele Situationen erfordern genau reguläre Ausdrücke und sonst nichts.

Das Ersetzen von nicht druckbaren Sonderzeichen durch harmlose Zeichen ist eine weitere gute Verwendung.

Ich kann mir natürlich vorstellen, dass es einige Codebasen gibt, die reguläre Ausdrücke zum Nachteil der Wartbarkeit überbeanspruchen. Das habe ich selbst noch nie gesehen. Ich wurde tatsächlich von Code-Reviewern gemieden, weil ich nicht genug reguläre Ausdrücke verwendet habe.

Chris Morley
quelle
10
Die Erfahrung zeigt, dass Regexes tatsächlich ein ziemlich schlechtes Werkzeug für die Validierung des E-Mail-Adressformats sind. Ein wirklich vollständiger Formatvalidator, der als regulärer Ausdruck implementiert ist, ist eine Monstrosität mit mehreren hundert Zeichen, während die meisten der kürzeren "gut genug" Validatoren, für deren Erstellung die meisten Benutzer 5 Minuten benötigen, große Kategorien gültiger, zu liefernder Adressen ablehnen.
Dave Sherohman
Ich höre dich, Alter. Ich habe über das "Gut genug" gesprochen, und obwohl die großen Schwaden theoretisch groß sein mögen, sollten Sie den Prozentsatz der Abdeckung berücksichtigen, den Sie in einem so kurzen Ausdruck erhalten. Ich habe auch die Monstrosität gesehen, aber was ist Ihre elegante Alternative?
Chris Morley
2
Ich habe so etwas wie \ w @ \ w +. \ W + verwendet, um die E-Mail-Adresse schnell in einem riesigen Verzeichnis von Dateien zu finden, in denen Geschwindigkeit wichtig war und einige falsch positive oder falsch negative Ergebnisse nicht wichtig waren. Der beste Weg, eine E-Mail-Adresse zu validieren, scheint darin zu bestehen, eine E-Mail an sie zu senden.
RossFabricant
Ja, E-Mail, die Adressspezifikation ist ein böses Durcheinander stackoverflow.com/questions/611775/…
Nick Van Brunt
@Nick, @Dave: Die Überprüfung der E- Mail-Adresse muss kein böses Durcheinander sein.
tchrist