Was ist mit "Jetzt hast du zwei Probleme" gemeint?


200

Es gibt ein populäres Zitat von Jamie Zawinski :

Einige Leute denken, wenn sie mit einem Problem konfrontiert werden: "Ich weiß, ich werde reguläre Ausdrücke verwenden." Jetzt haben sie zwei Probleme.

Wie ist dieses Zitat zu verstehen?


46
Das zweite Problem ist, dass sie Regex verwenden und das erste Problem immer noch nicht gelöst haben, daher 2 Probleme.
Ampt

24
@Euphoric - eigentlich guter Code ist kurz - aber ohne kryptisch prägnant zu sein.
Steve314

24
@IQAndreas: Ich denke, es soll halb-humorvoll sein. Der Kommentar, der gemacht wird, ist, dass, wenn Sie nicht vorsichtig sind, die Verwendung von regulären Ausdrücken die Dinge eher verschlechtern als verbessern kann.
FrustratedWithFormsDesigner

145
Einige Leute denken, wenn sie versuchen, etwas zu erklären: "Ich weiß, ich werde ein Jamie Zawinski-Zitat verwenden." Jetzt müssen sie zwei Dinge erklären.
Detly

Antworten:


220

Einige Programmiertechnologien werden von Programmierern im Allgemeinen nicht gut verstanden ( reguläre Ausdrücke , Gleitkomma , Perl , AWK , IoC ... und andere ).

Dies können erstaunlich leistungsstarke Tools sein, um die richtigen Probleme zu lösen. Insbesondere reguläre Ausdrücke sind sehr nützlich, um reguläre Sprachen abzugleichen. Und da ist der Kern des Problems: Nur wenige Menschen können eine reguläre Sprache beschreiben (es ist Teil der Informatiktheorie / Sprachwissenschaft, die lustige Symbole verwendet - das können Sie in der Chomsky-Hierarchie nachlesen ).

Wenn Sie diese Dinge falsch anwenden, ist es unwahrscheinlich, dass Sie Ihr ursprüngliches Problem tatsächlich gelöst haben. Die Verwendung eines regulären Ausdrucks zur Übereinstimmung mit HTML (ein viel zu häufiges Vorkommen) führt dazu, dass Sie Randfälle verpassen. Und jetzt haben Sie immer noch das ursprüngliche Problem, das Sie nicht gelöst haben, und einen weiteren subtilen Fehler, der durch die Verwendung der falschen Lösung behoben wurde.

Das soll nicht heißen, dass reguläre Ausdrücke nicht verwendet werden sollten, sondern dass man versuchen sollte zu verstehen, welche Probleme sie lösen können und welche nicht und mit Bedacht.

Der Schlüssel zur Wartung der Software ist das Schreiben von wartbarem Code. Die Verwendung regulärer Ausdrücke kann diesem Ziel entgegenwirken. Wenn Sie mit regulären Ausdrücken arbeiten, haben Sie einen Mini-Computer (insbesondere einen nicht deterministischen Automaten mit endlichen Zuständen ) in einer speziellen domänenspezifischen Sprache geschrieben. Es ist einfach, das 'Hallo Welt'-Äquivalent in dieser Sprache zu schreiben und ein rudimentäres Vertrauen in diese Sprache zu gewinnen. Um jedoch zu vermeiden, dass zusätzliche Fehler geschrieben werden, die sehr schwer zu identifizieren und zu beheben sind (weil Sie sind nicht Teil des Programms, in dem sich der reguläre Ausdruck befindet.

Jetzt haben Sie ein neues Problem. Sie haben das Tool des regulären Ausdrucks ausgewählt, um es zu lösen (wenn es unangemessen ist), und Sie haben jetzt zwei Bugs, die beide schwerer zu finden sind, weil sie in einer anderen Abstraktionsebene versteckt sind.


8
Ich bin nicht sicher, ob Perl selbst in eine Liste von Technologien gehört, die von Programmierern nicht gut verstanden werden;)
crad

21
@crad es ist mehr, dass es auch über Perl gesagt wurde ... Viele Leute haben es dort popularisiert gehört. Ich mag immer noch das Gleitkomma im Rand Talk: "Jetzt haben Sie 2.00000152 Probleme"

56
@crad Einige Leute denken, wenn sie mit einem Problem konfrontiert werden: "Ich weiß, ich werde Perl verwenden." Jetzt haben sie Probleme mit $ (^ @ #% () ^%) (#).
Michael Hampton

4
@Jens, wenn überhaupt, die zusätzliche Leistung des PCRE im Vergleich zu herkömmlichem Regex macht es zu einer verlockenderen und schwieriger zu wartenden Lösung . Die endlichen Automaten, mit denen die PCRE übereinstimmt, werden in Erweitern endlicher Automaten, um Perl-kompatible reguläre Ausdrücke effizient abzugleichen , untersucht. Zumindest mit der traditionellen Regex kann man sich ohne allzu große Mühe darum kümmern, wenn die notwendigen Konzepte erst einmal verstanden sind.

6
Sie machen einen guten Punkt. reguläre Ausdrücke sind effektiv eine zweite, nicht triviale Sprache. Selbst wenn der ursprüngliche Programmierer in der Hauptsprache und im Geschmack des verwendeten Regex kompetent ist, bedeutet das Hinzufügen in einer "zweiten Sprache" geringere Chancen, dass die Betreuer beide kennen. Ganz zu schweigen davon, dass die Lesbarkeit von Regex oft schlechter ist als die der "Host" -Sprache.
JS.

95

Reguläre Ausdrücke - insbesondere nicht triviale - sind möglicherweise schwer zu codieren, zu verstehen und zu pflegen. Sie müssen sich nur die Anzahl der Fragen ansehen, die auf dem Stack Overflow-Tag angegeben sind und bei [regex]denen der Fragesteller angenommen hat, dass die Antwort auf sein Problem ein regulärer Ausdruck ist, und die anschließend hängengeblieben sind. In vielen Fällen kann (und sollte) das Problem auf andere Weise gelöst werden.

Wenn Sie sich also für die Verwendung eines regulären Ausdrucks entscheiden, treten zwei Probleme auf:

  1. Das ursprüngliche Problem, das Sie lösen wollten.
  2. Die Unterstützung eines Regex.

Grundsätzlich denke ich, er meint, Sie sollten nur einen regulären Ausdruck verwenden, wenn es keine andere Möglichkeit gibt, Ihr Problem zu lösen. Eine andere Lösung wird wahrscheinlich einfacher zu programmieren, zu warten und zu unterstützen sein. Es kann langsamer oder weniger effizient sein, aber wenn dies nicht kritisch ist, sollte die einfache Wartung und der Support das übergeordnete Anliegen sein.


27
Und was noch schlimmer ist: Sie sind gerade mächtig genug, um die Leute dazu zu bringen, mit ihnen Dinge zu analysieren, die sie nicht können, wie beispielsweise HTML. Siehe die zahlreichen Fragen zu SO zu "Wie analysiere ich HTML?"
Frank Shearar

6
Für bestimmte Situationen ist Regex fantastisch. In vielen anderen Fällen nicht so sehr. Am anderen Ende ist es eine schreckliche Grube der Verzweiflung. Das Problem tritt häufig auf, wenn jemand zum ersten Mal etwas über sie erfährt und Anwendungen überall zu sehen beginnt. Ein anderes berühmtes Sprichwort: "Wenn Sie nur einen Hammer haben, sieht alles aus wie ein Nagel."
Todd Williamson

3
Bedeutet dies, dass es aufgrund der Anzahl der Fragen im Tag SO [c #] am schwierigsten ist, die Programmiersprache zu verstehen?

2
Ich würde viel lieber einen komplexen regulären Ausdruck sehen als eine lange Reihe von Aufrufen von String-Methoden. OTOH, ich hasse es wirklich, wenn reguläre Ausdrücke missbraucht werden, um komplexe Sprachen zu analysieren.
Kevin Cline

5
"Grundsätzlich denke ich, er meint, Sie sollten nur einen regulären Ausdruck verwenden, wenn es keine andere Möglichkeit gibt, Ihr Problem zu lösen. Jede andere Lösung wird einfacher zu programmieren, zu warten und zu unterstützen sein." - stimme überhaupt nicht zu. Regexes sind hervorragende Werkzeuge, man muss nur ihre Grenzen kennen. Viele Aufgaben können mit regulären Ausdrücken eleganter codiert werden. (aber um nur ein Beispiel zu nennen, Sie sollten sie nicht zum Parsen von HTML verwenden)
Karoly Horvath

69

Es ist meist ein Scherz, wenn auch mit einem Körnchen Wahrheit.

Es gibt einige Aufgaben, für die reguläre Ausdrücke hervorragend geeignet sind. Ich habe einmal 500 manuell geschriebene Zeilen rekursiven Parser-Codes durch einen regulären Ausdruck ersetzt, dessen vollständiges Debugging etwa 10 Minuten in Anspruch nahm. Man sagt, reguläre Ausdrücke seien schwer zu verstehen und zu debuggen, aber angemessen angewandte sind bei weitem nicht so schwer zu debuggen wie ein riesiger handgefertigter Parser. In meinem Beispiel dauerte es zwei Wochen, um alle Edge-Fälle der Nicht-Regex-Lösung zu debuggen.

Um jedoch Onkel Ben zu paraphrasieren:

Mit großer Ausdruckskraft geht eine große Verantwortung einher.

Mit anderen Worten, reguläre Ausdrücke verleihen Ihrer Sprache mehr Ausdruckskraft, aber das überträgt dem Programmierer mehr Verantwortung, den am besten lesbaren Ausdrucksmodus für eine bestimmte Aufgabe zu wählen.

Einige Dinge sehen auf den ersten Blick wie eine gute Aufgabe für reguläre Ausdrücke aus, sind es aber nicht. Zum Beispiel alles mit verschachtelten Token wie HTML. Manchmal wird ein regulärer Ausdruck verwendet, wenn eine einfachere Methode klarer ist. Zum Beispiel string.endsWith("ing")ist leichter zu verstehen als der entsprechende reguläre Ausdruck. Manchmal versuchen die Leute, ein großes Problem in ein einzelnes Regex zu packen, wo es angemessener ist, es in Stücke zu zerbrechen. Manchmal schaffen es die Benutzer nicht, geeignete Abstraktionen zu erstellen, und wiederholen einen regulären Ausdruck immer wieder, anstatt eine gut benannte Funktion zu erstellen, die denselben Job ausführt (möglicherweise intern mit einem regulären Ausdruck implementiert).

Aus irgendeinem Grund neigen reguläre Ausdrücke dazu, einen toten Winkel zu normalen Softwareentwicklungsprinzipien wie Single Responsibility und DRY zu bilden. Das ist der Grund, warum selbst Menschen, die sie lieben, sie manchmal als problematisch empfinden.


10
Hat Onkel Ben nicht auch "Jedes Mal perfekte Ergebnisse" gesagt? Vielleicht ist das der Grund, warum die Leute mit Regexen so glücklich werden ...
Andrzej Doyle

4
Das Problem mit Regex bezüglich HTML, das unerfahrene Entwickler auslöst, ist, dass HTML eine kontextfreie Grammatik hat, die nicht regelmäßig ist: Regex kann für ein einfaches HTML- (oder XML-) Parsen verwendet werden (z. B. das Abrufen einer URL von einem benannten Ankertag), aber ist für nichts komplexes gut geeignet. Dafür ist DOM-Parsing besser geeignet. Verwandte Lektüre: Chomsky-Hierarchie .

53

Jeff Atwood legt eine andere Interpretation in einem Blog-Beitrag vor, der genau dieses Zitat behandelt: Reguläre Ausdrücke: Jetzt haben Sie zwei Probleme (danke an Euphoric für den Link)

Wenn wir den vollständigen Text von Jamies Beiträgen im ursprünglichen Thread von 1997 analysieren, finden wir Folgendes:

Perls Natur ermutigt die Verwendung regulärer Ausdrücke fast unter Ausschluss aller anderen Techniken; Sie sind bei weitem der "offensichtlichste" Weg (zumindest für Menschen, die es nicht besser wissen), um von Punkt A nach Punkt B zu gelangen.

Das erste Zitat ist zu glitschig, um ernst genommen zu werden. Aber dem stimme ich voll und ganz zu. Hier ist der Punkt, den Jamie anstrebte: Nicht dass reguläre Ausdrücke per se böse sind, sondern dass übermäßiger Gebrauch von regulären Ausdrücken böse ist.

Auch wenn Sie es vollständig reguläre Ausdrücke verstehen, laufen Sie in The Golden Hammer Problem, ein Problem mit regulären Ausdrücken zu lösen versuchen, wenn es wäre einfacher und klarer gewesen sein , die gleiche Sache mit regelmäßigem Code zu tun (siehe auch Coding: Regex Verwendung Regex-Missbrauch ).

Es gibt einen weiteren Blog-Beitrag, der sich mit dem Kontext des Zitats befasst und ausführlicher ist als Atwood: Jeffrey Friedls Blog: Quelle des berühmten Zitats „Jetzt hast du zwei Probleme“


3
Dies ist meines Erachtens die beste Antwort, da sie den Kontext erweitert. Jwz 'Kritik an Regexen betraf Perl so sehr wie alles andere.
Evicatos

3
@Evicatos In einem anderen Blog-Beitrag wurden sogar noch mehr Untersuchungen zum selben Thema von 1997 durchgeführt: regex.info/blog/2006-09-15/247
IQAndreas

30

Es gibt ein paar Dinge, die mit diesem Zitat geschehen.

  1. Das Zitat ist eine Wiederholung eines früheren Witzes:

    Immer wenn jemand mit einem Problem konfrontiert wird, sagen manche Leute "Lasst uns AWK benutzen." Jetzt haben sie zwei Probleme. - D. Tilbrook

    Es ist ein Witz und eine echte Ausgrabung, aber es ist auch eine Möglichkeit, Regex als schlechte Lösung hervorzuheben, indem es mit anderen schlechten Lösungen verknüpft wird. Es ist ein großartiger, nur ernster Moment.

  2. Für mich - wohlgemerkt, dieses Zitat ist absichtlich offen für Interpretationen - ist die Bedeutung eindeutig. Das Problem ist noch nicht gelöst, wenn Sie lediglich die Idee der Verwendung eines regulären Ausdrucks ankündigen. Darüber hinaus haben Sie die kognitive Komplexität des Codes erhöht, indem Sie eine zusätzliche Sprache mit Regeln hinzugefügt haben, die sich von der verwendeten Sprache unterscheiden.

  3. Obwohl es witzig ist, müssen Sie die Komplexität einer Nicht-Regex-Lösung mit der Komplexität der Regex-Lösung und der zusätzlichen Komplexität des Einbindens von Regexen vergleichen. Trotz der zusätzlichen Kosten für das Hinzufügen von Regexen kann es sich lohnen, ein Problem mit einem Regex zu lösen.


21

Regelmäßige Ausdrücke lassen keinen anderen unformatierten Inhalt erkennen, in der Tat ist es unwahrscheinlich, dass dieses Textstück gelesen wird, da einige Implementierungen keine Formatierung zulassen und die Menschen überhaupt nicht wissen, was sie tun.

(Reguläre Ausdrücke sind nicht schlechter zu lesen oder zu pflegen als jeder andere unformatierte Inhalt. In der Tat ist ein regulärer Ausdruck wahrscheinlich einfacher zu lesen als dieser Text hier. Leider haben sie einen schlechten Ruf, da einige Implementierungen Formatierungen und Personen im Allgemeinen nicht zulassen Ich weiß nicht, dass du es schaffst.)


Hier ist ein triviales Beispiel:

^(?:[^,]*+,){21}[^,]*+$


Was sowieso nicht so schwer zu lesen oder zu warten ist, aber noch einfacher, wenn es so aussieht:

(?x)    # enables comments, so this whole block can be used in a regex.
^       # start of string

(?:     # start non-capturing group
  [^,]*+  # as many non-commas as possible, but none required
  ,       # a comma
)       # end non-capturing group
{21}    # 21 of previous entity (i.e. the group)

[^,]*+  # as many non-commas as possible, but none required

$       # end of string

Das ist ein übertriebenes Beispiel (Kommentieren $ist vergleichbar mit Kommentieren i++), aber es sollte eindeutig kein Problem geben, das zu lesen, zu verstehen und aufrechtzuerhalten.


Solange klar ist, wann reguläre Ausdrücke geeignet sind und wann sie eine schlechte Idee sind, ist nichts daran auszusetzen, und meistens gilt das Zitat von JWZ nicht wirklich.


1
Klar, aber ich suche keine Diskussionen über die Vorzüge von Regexs, und ich möchte nicht, dass diese Diskussion so verläuft. Ich versuche nur zu verstehen, worauf er hinaus wollte.
Paul Biggar

1
Dann sagt Ihnen der Link im Kommentar von livibetter, was Sie wissen müssen. Diese Antwort zeigt nur, dass reguläre Ausdrücke nicht dunkel sein müssen, und daher ist das Zitat Unsinn.
Peter Boughton

8
Was ist der Sinn der Verwendung *+? Wie ist das anders (funktional) als nur *?
Timwi

1
Auch wenn das, was Sie sagen, wahr sein mag, beantwortet es diese spezielle Frage nicht. Ihre Antwort lautet: "Meiner Meinung nach stimmt dieses Zitat normalerweise nicht." Die Frage ist nicht, ob es wahr ist oder nicht, sondern was das Zitat bedeutet.
Bryan Oakley

2
*+In diesem Fall hat das buchstäblich keinen Sinn . Alles ist verankert und kann in einem Durchgang von einem Automaten abgeglichen werden, der bis zu 22 zählen kann. Der richtige Modifikator für diese Nicht-Kommasätze ist einfach alt *. (Außerdem sollte es hier keine Unterschiede zwischen gierigen und nicht-gierigen Matching-Algorithmen geben. Dies ist ein äußerst einfacher Fall.)
Donal Fellows

14

Neben der Antwort von ChrisF, dass reguläre Ausdrücke "schwer zu codieren, zu verstehen und zu pflegen sind", ist noch schlimmer: Sie sind nur so mächtig, dass die Leute versuchen, sie zum Parsen von Dingen zu verwenden, die sie nicht können, wie beispielsweise HTML. Siehe die zahlreichen Fragen zu SO zu "Wie analysiere ich HTML?" Zum Beispiel die epischste Antwort in SO!


14

Reguläre Ausdrücke sind sehr mächtig, haben aber ein kleines und ein großes Problem. Sie sind schwer zu schreiben und fast unmöglich zu lesen.

Im besten Fall löst die Verwendung des regulären Ausdrucks das Problem, sodass Sie nur das Wartungsproblem des komplizierten Codes haben. Wenn Sie den regulären Ausdruck nicht richtig verstehen, haben Sie sowohl das ursprüngliche Problem als auch das Problem mit unlesbarem Code, der nicht funktioniert.

Manchmal werden reguläre Ausdrücke als Nur-Schreib-Code bezeichnet. Angesichts eines regulären Ausdrucks, der korrigiert werden muss, ist es oft schneller, von vorne zu beginnen, als zu versuchen, den Ausdruck zu verstehen.


1
Das eigentliche Problem ist, dass reguläre Ausdrücke zB keinen Parser implementieren können, da sie nicht zählen können, wie tief sie derzeit verschachtelt sind.

4
@ Thorbjørn Ravn Andersen: Das ist eher eine Einschränkung als ein Problem. Es ist nur ein Problem, wenn Sie versuchen, reguläre Ausdrücke dafür zu verwenden, und dann ist es kein Problem mit den regulären Ausdrücken, sondern ein Problem mit Ihrer Wahl der Methode.
Guffa

1
Sie können REs gut für den Lexer verwenden (na ja, für die meisten Sprachen), aber das Zusammenstellen des Token-Streams zu einem Analysebaum (dh Parsen ) ist formal nicht möglich.
Donal Fellows

10

Das Problem ist, dass Regex ein kompliziertes Biest ist und Sie Ihr Problem nur lösen, wenn Sie Regex perfekt einsetzen. Andernfalls treten zwei Probleme auf: das ursprüngliche Problem und der reguläre Ausdruck.

Sie behaupten, dass es die Arbeit von hundert Codezeilen erledigen kann, aber Sie könnten auch argumentieren, dass 100 Zeilen klarer, präziser Code besser sind als eine Zeile regulärer Ausdrücke.

Wenn Sie einen Beweis dafür benötigen: Sie können diesen SO Classic ausprobieren oder einfach den SO Regex-Tag durchkämmen


8
Keine der Behauptungen in Ihrem ersten Satz ist wahr. Regex ist nicht besonders kompliziert und wie kein anderes Tool müssen Sie es perfekt kennen, um Probleme damit zu lösen. Das ist nur FUD. Ihr zweiter Absatz ist einfach lächerlich: Natürlich können Sie das Argument vorbringen. Aber es ist kein guter.
Konrad Rudolph

1
@KonradRudolph Ich denke, die Tatsache, dass es zahlreiche Tools zur Generierung und Validierung von Regex gibt , zeigt, dass Regex ein komplizierter Mechanismus ist. Es ist nicht für den Menschen lesbar (beabsichtigt) und kann für jemanden, der einen Teil des Codes ändert oder schreibt, der Regex verwendet, zu einer vollständigen Änderung des Ablaufs führen. Was den zweiten Teil anbelangt, denke ich, dass dies durch die umfassende Gruppierung von Wissen zu P.SE und durch das Sprichwort "Das Debuggen von Code ist doppelt so schwierig wie das Schreiben. Wenn Sie also den cleversten Code schreiben, den Sie können, Sie." sind per definitionem nicht schlau genug, um es zu debuggen "
Ampt

2
Das ist kein richtiges Argument. Ja, sicher, dass reguläre Ausdrücke komplex sind. Aber auch andere Programmiersprachen. Regex ist erheblich weniger komplex als die meisten anderen Sprachen, und die Tools, die für Regex existieren, werden von Entwicklungstools für andere Sprachen in den Schatten gestellt (FWIW Ich arbeite intensiv mit Regex und habe solche Tools noch nie verwendet…). Es ist eine einfache Wahrheit, dass selbst komplexe reguläre Ausdrücke einfacher sind als gleichwertiger nicht-regulärer Parsing-Code.
Konrad Rudolph

@KonradRudolph Ich denke, wir sind uns über die Definition des Wortes einfach nicht einig. Ich gebe Ihnen , dass regex mehr sein kann effizient oder noch leistungsfähiger , aber ich glaube nicht , dass einfach das Wort, das zu niemandem in den Sinn kommt , wenn man von regex denken.
Ampt

Vielleicht tun wir das, aber meine Definition ist umsetzbar: Ich verstehe einfach, leicht zu verstehen, leicht zu warten, geringe Anzahl von versteckten Fehlern usw. Natürlich wird ein komplexer regulärer Ausdruck auf den ersten Blick nicht sehr nachvollziehbar aussehen. Aber das gleiche gilt für ein gleichwertiges nicht-regex Stück Code. Ich habe nie gesagt, dass Regex einfach ist. Ich sage, sie sind einfacher - ich vergleiche. Das ist wichtig.
Konrad Rudolph

7

Die Bedeutung besteht aus zwei Teilen:

  • Erstens haben Sie das ursprüngliche Problem nicht gelöst.
    Dies ist wahrscheinlich darauf zurückzuführen, dass reguläre Ausdrücke häufig unvollständige Lösungen für häufig auftretende Probleme bieten .
  • Zweitens haben Sie jetzt zusätzliche Schwierigkeiten hinzugefügt, die mit der von Ihnen ausgewählten Lösung verbunden sind.
    Bei regulären Ausdrücken bezieht sich die zusätzliche Schwierigkeit wahrscheinlich auf die Komplexität, Wartbarkeit oder die zusätzliche Schwierigkeit, reguläre Ausdrücke an ein Problem anzupassen, das nicht gelöst werden sollte.

7

Wenn Sie 2014 danach fragen, wäre es interessant, sich auf die Programmiersprachenideologien des Kontextes von 1997 im Vergleich zum heutigen Kontext zu konzentrieren. Ich werde hier nicht auf diese Debatte eingehen, aber die Meinungen über Perl und Perl selbst haben sich stark geändert.

Um jedoch in einem Kontext von 2013 zu bleiben ( de l'eau a coulé sous les ponts depuis), würde ich vorschlagen, sich auf die Nachstellung von Zitaten mit einem berühmten XKCD-Comic zu konzentrieren, der ein direktes Zitat von Jamie Zawinski ist :

Ein Comic von XKCD über Regexes, Perl und Probleme

Zuerst hatte ich Probleme, diesen Comic zu verstehen, weil er sich auf das Zawinski-Zitat und ein Zitat eines Jay-z-Liedtextes und eine Referenz von GNU- program --help -zFlag 2 bezog . Es war also zu viel Kultur, als dass ich ihn verstehen könnte.

Ich wusste, dass es Spaß machte, ich fühlte es, aber ich wusste nicht wirklich warum. Die Leute machen oft Witze über Perl und Regexes, vor allem, weil es nicht die angesagteste Programmiersprache ist und sie nicht wirklich wissen, warum es Spaß machen soll ... Vielleicht, weil Perl-Händler alberne Dinge tun .

Das anfängliche Zitat scheint also ein sarkastischer Witz zu sein, der auf realen Problemen (Schmerzen?) Beruht, die durch das Programmieren mit Werkzeugen verursacht werden, die weh tun. So wie ein Hammer einen Maurer verletzen kann, programmiert er mit Werkzeugen, die ein Entwickler nicht wählen würde, wenn er verletzen könnte (das Gehirn, die Gefühle). Manchmal große Debatten über das Tool ist die beste auftritt, aber es ist fast wertlos weil es ein Problem ist Ihren Geschmack oder Ihr Programmierteam Geschmack , kultureller oder wirtschaftlicher Gründe. Ein weiterer hervorragender XKCD-Comic dazu:

Ein Comic von XKCD über Debatten über Programmiertools

Ich kann verstehen, dass Menschen Schmerzen mit Regexen haben, und sie glauben, dass ein anderes Tool besser für das geeignet ist, wofür Regexen entwickelt wurden. Da @ karl-bielefeldt Ihre Frage mit großer Expressivität beantwortet, kommt eine große Verantwortung auf , und Regexes sind davon besonders betroffen. Wenn ein Entwickler sich nicht darum kümmert, wie er mit regulären Ausdrücken umgeht, wird es für Leute, die den Code später pflegen, schlimm sein.

Ich werde mit dieser Antwort über die Nachstellung von Zitaten durch ein Zitat abschließen, das ein typisches Beispiel aus Perl Best Practices von Damian Conw ay zeigt (ein Buch von 2005).

Er erklärt das Schreiben eines Musters wie folgt:

m{'[^\\']*(?:\\.[^\\']*)*'}

... ist nicht akzeptabler als ein Programm wie dieses zu schreiben :

sub'x{local$_=pop;sub'_{$_>=$_[0
]?$_[1]:$"}_(1,'*')._(5,'-')._(4
,'*').$/._(6,'|').($_>9?'X':$_>8
?'/':$")._(8,'|').$/._(2,'*')._(
7,'-')._(3,'*').$/}print$/x($=).
x(10)x(++$x/10).x($x%10)while<>;

Aber es kann umgeschrieben werden , es ist immer noch nicht schön, aber zumindest ist es jetzt überlebensfähig.

# Match a single-quoted string efficiently...
m{ '            # an opening single quote
    [^\\']*     # any non-special chars (i.e., not backslash or single quote)
    (?:         # then all of...`
    \\ .        # any explicitly backslashed char
    [^\\']*     #    followed by any non-special chars
    )*          # ...repeated zero or more times
    '           # a closing single quote
}x

Diese Art von rechteckigem Code ist das zweite Problem, bei dem es sich nicht um reguläre Ausdrücke handelt, die klar, wartbar und lesbar formatiert werden können.


2
/* Multiply the first 10 values in an array by 2. */ for (int i = 0 /* the loop counter */; i < 10 /* continue while it is less than 10 */; ++i /* and increment it by 1 in each iteration */) { array[i] *= 2; /* double the i-th element in the array */ }
5gon12eder

6

Wenn es eine Sache gibt, die Sie aus der Informatik lernen sollten, dann ist das die Chomsky-Hierarchie . Ich würde sagen, dass alle Probleme mit regulären Ausdrücken von dem Versuch herrühren, damit eine kontextfreie Grammatik zu analysieren. Wenn Sie den Verschachtelungsebenen in CFG ein Limit auferlegen können (oder glauben, Sie können ein Limit auferlegen), erhalten Sie diese langen und komplexen regulären Ausdrücke.


1
Ja! Menschen, die reguläre Ausdrücke ohne diesen Teil des CS-Hintergrunds lernen, verstehen nicht immer, dass es nur einige Dinge gibt, die ein Regex mathematisch nicht kann.
Benzado

5

Reguläre Ausdrücke eignen sich eher für die Tokenisierung als für das vollständige Parsen.

Aber eine überraschend große Menge von Dingen, die Programmierer analysieren müssen, können von einer regulären Sprache analysiert werden (oder, schlimmer noch, fast von einer regulären Sprache analysiert werden und wenn Sie nur ein bisschen mehr Code schreiben ...).

Wenn man sich also an "aha, ich muss Text auseinander nehmen, ich verwende einen regulären Ausdruck" gewöhnt hat, ist es einfach, diesen Weg zu gehen, wenn man etwas benötigt, das näher an einem Push-Down-Automaten, einem CFG-Parser oder einem anderen liegt noch mächtigere Grammatiken. Das endet normalerweise in Tränen.

Ich denke also, dass das Zitat nicht so sehr reguläre Ausdrücke zuschlägt, sie haben ihren Nutzen (und sind gut genutzt, sie sind in der Tat sehr nützlich), aber das übermäßige Vertrauen in reguläre Ausdrücke (oder insbesondere die unkritische Wahl von ihnen). .


3

jwz ist mit diesem Zitat einfach von seinem Rocker. reguläre Ausdrücke unterscheiden sich nicht von anderen Sprachfeatures - einfach zu verwechseln, schwierig zu verwenden, manchmal mächtig, manchmal unangemessen, oft gut dokumentiert, oft nützlich.

Das Gleiche gilt für Gleitkomma-Arithmetik, Closures, Objektorientierung, asynchrone E / A oder alles andere, was Sie benennen können. Wenn Sie nicht wissen, was Sie tun, können Programmiersprachen Sie traurig machen.

Wenn Sie der Meinung sind, dass reguläre Ausdrücke schwer zu lesen sind, lesen Sie die entsprechende Parser-Implementierung, um das betreffende Muster zu verarbeiten. Regexes gewinnen oft, weil sie kompakter sind als vollständige Parser ... und in den meisten Sprachen sind sie auch schneller.

Lassen Sie sich nicht davon abhalten, reguläre Ausdrücke (oder andere Sprachfunktionen) zu verwenden, da ein sich selbst fördernder Blogger uneingeschränkte Aussagen macht. Probieren Sie es aus und sehen Sie, was für Sie funktioniert.


1
FWIW, Gleitkomma-Arithmetik ist zwar schwieriger als REs, erscheint aber einfacher. In acht nehmen! (Zumindest tricky REs neigen dazu, gefährlich auszusehen.)
Donal Fellows

3

Meine liebste und ausführlichste Antwort darauf gibt der berühmte Rob Pike in einem Blog-Beitrag, der aus einem internen Google-Codekommentar stammt: http://commandcenter.blogspot.ch/2011/08/regular-expressions-in-lexing- and.html

Die Zusammenfassung ist, dass es nicht so ist, dass sie schlecht sind , aber sie werden häufig für Aufgaben verwendet, für die sie nicht unbedingt geeignet sind, insbesondere wenn es darum geht, Eingaben zu lexen und zu analysieren.

Reguläre Ausdrücke sind schwer zu schreiben, schwer gut zu schreiben und können im Vergleich zu anderen Technologien teuer sein. Lexer hingegen sind recht einfach richtig zu schreiben (wenn auch nicht so kompakt) und sehr einfach zu testen. Erwägen Sie die Suche nach alphanumerischen Bezeichnern. Es ist nicht allzu schwer, den regulären Ausdruck (so etwas wie "[a-ZA-Z _] [a-ZA-Z_0-9] *") zu schreiben, aber es ist wirklich nicht viel schwieriger, ihn als einfache Schleife zu schreiben. Die Leistung der Schleife wird jedoch viel höher sein und viel weniger Code unter der Decke beinhalten. Eine Bibliothek mit regulären Ausdrücken ist eine große Sache. Die Verwendung eines Identifikators zum Parsen entspricht der Verwendung eines Ferrari, um Milch in den Laden zu holen.

Er sagt viel mehr als das und argumentiert, dass reguläre Ausdrücke nützlich sind, z. B. um Muster in Texteditoren auf einmal abzugleichen, aber selten in kompiliertem Code verwendet werden sollten, und so weiter. Es ist eine Lektüre wert.


0

Dies hängt mit Alan Perlis 'Epigramm Nr. 34 zusammen:

Die Zeichenfolge ist eine strenge Datenstruktur, und überall, wo sie übergeben wird, kommt es zu doppelten Prozessen. Es ist ein perfektes Fahrzeug zum Verstecken von Informationen.

Wenn Sie also die Zeichenfolge als Datenstruktur auswählen (und natürlich Regex-basierten Code als Algorithmus, um sie zu manipulieren), haben Sie ein Problem, auch wenn es funktioniert: Schlechtes Design um eine unangemessene Darstellung von Daten, die schwer zu bearbeiten sind verlängern und ineffizient.

Oft funktioniert es jedoch nicht: Das ursprüngliche Problem ist nicht gelöst, und in diesem Fall treten zwei Probleme auf.


0

Regexe werden häufig zum schnellen und unsauberen Parsen von Text verwendet. Sie eignen sich hervorragend zum Ausdrücken von Mustern, die etwas komplexer sind als nur eine einfache Zeichenfolgenübereinstimmung.

Mit zunehmender Komplexität von Regexen erheben sich jedoch mehrere Probleme.

  1. Die Syntax von regulären Ausdrücken ist für einfache Übereinstimmungen optimiert, die meisten Zeichen stimmen selbst überein. Das ist gut für einfache Muster geeignet, aber sobald Sie mehr als ein paar Verschachtelungsebenen erreicht haben, sehen Sie eher wie Zeilenrauschen aus als wie gut strukturierter Code. Ich schätze, Sie könnten einen regulären Ausdruck als eine Reihe von verketteten Zeichenfolgen mit Einrückungen und Kommentaren dazwischen schreiben, um die Struktur des Codes darzustellen, aber es scheint selten zu sein, dass dies tatsächlich passiert.
  2. Nur bestimmte Arten der Textübereinstimmung eignen sich gut für reguläre Ausdrücke. Häufig erhalten Sie einen schnellen und schmutzigen Parser auf der Basis von Regex für eine Art von Markup-Sprache, aber dann versuchen Sie, mehr Eckfälle abzudecken, und stellen fest, dass die Regex immer komplexer und immer weniger lesbar werden
  3. Die zeitliche Komplexität eines regulären Ausdrucks ist möglicherweise nicht eindeutig. Es ist nicht so schwierig, ein Muster zu erhalten, das bei Übereinstimmung hervorragend funktioniert, jedoch unter bestimmten Umständen eine O (2 ^ n) -Komplexität aufweist .

Daher ist es allzu einfach, mit einem Textverarbeitungsproblem zu beginnen, reguläre Ausdrücke darauf anzuwenden und am Ende zwei Probleme zu lösen, das ursprüngliche Problem, das Sie zu lösen versuchten, und die regulären Ausdrücke zu behandeln, die zu lösen versuchen (aber nicht richtig lösen). das ursprüngliche Problem.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.