Co oznacza „teraz masz dwa problemy”?


200

Jest popularny cytat Jamie Zawinski :

Niektórzy ludzie, gdy napotykają problem, myślą: „Wiem, użyję wyrażeń regularnych”. Teraz mają dwa problemy.

Jak należy rozumieć ten cytat?


46
Drugi problem polega na tym, że używają wyrażeń regularnych i nadal nie rozwiązali pierwszego problemu, stąd 2 problemy.
Ampt

24
@Euforia - właściwie dobry kod jest krótki - ale bez tajemniczej zwięzłości.
Steve314,

24
@IQAndreas: Myślę, że ma być humorystyczny. Komentowany komentarz jest taki, że jeśli nie będziesz ostrożny, użycie wyrażeń regularnych może pogorszyć sytuację, a nie poprawić.
FrustratedWithFormsDesigner

145
Niektórzy ludzie, próbując coś wyjaśnić, myślą: „Wiem, użyję cytatu Jamiego Zawińskiego”. Teraz mają dwie rzeczy do wyjaśnienia.
detly

Odpowiedzi:


220

Niektóre technologie programowania nie są na ogół dobrze rozumiane przez programistów ( wyrażenia regularne , zmiennoprzecinkowe , Perl , AWK , IoC ... i inne ).

Mogą to być niezwykle potężne narzędzia do rozwiązywania właściwego zestawu problemów. Zwłaszcza wyrażenia regularne są bardzo przydatne do dopasowania języków regularnych. I sedno problemu: niewiele osób wie, jak opisać zwykły język (jest to część teorii / lingwistyki komputerowej, która używa zabawnych symboli - o tym można przeczytać w hierarchii Chomsky'ego ).

Jeśli masz do czynienia z tymi rzeczami, jeśli użyjesz ich źle, jest mało prawdopodobne, że rzeczywiście rozwiązałeś swój pierwotny problem. Korzystanie z wyrażeń regularnych, aby dopasować HTML (a zbyt częstym zjawiskiem) będzie oznaczać, że będzie przegap przypadki krawędzi. A teraz nadal masz pierwotny problem, którego nie rozwiązałeś, i kolejny subtelny błąd, który został wprowadzony przy użyciu niewłaściwego rozwiązania.

Nie oznacza to, że nie należy używać wyrażeń regularnych, ale raczej należy pracować, aby zrozumieć, jaki zestaw problemów można rozwiązać, a których nie można rozwiązać i rozsądnie z nich korzystać.

Kluczem do utrzymania oprogramowania jest pisanie możliwego do utrzymania kodu. Używanie wyrażeń regularnych może być sprzeczne z tym celem. Podczas pracy z wyrażeniami regularnymi napisałeś mini komputer (w szczególności niedeterministyczny automat skończony ) w specjalnym języku specyficznym dla domeny. Łatwo jest napisać odpowiednik „Witaj świecie” w tym języku i zyskać w nim szczerą pewność siebie, ale dalsza poprawa wymaga zrozumienia zwykłego języka, aby uniknąć pisania dodatkowych błędów, które mogą być bardzo trudne do zidentyfikowania i naprawienia (ponieważ nie są częścią programu, w którym znajduje się wyrażenie regularne).

Więc teraz masz nowy problem; wybrałeś narzędzie wyrażenia regularnego, aby je rozwiązać (gdy jest nieodpowiednie) i masz teraz dwa błędy, z których oba są trudniejsze do znalezienia, ponieważ są ukryte w innej warstwie abstrakcji.


8
Nie jestem pewien, czy sam perl należy do listy technologii, które nie są dobrze rozumiane przez programistów;)
crad

21
@crad to więcej, niż mówiono o perlu ... Wiele osób słyszało, że się tam spopularyzowało. Nadal podoba mi się zmiennoprzecinkowy jeden w rozmowie randkowej: „Teraz masz problemy z 2.00000152”

56
@crad Niektórzy ludzie, gdy napotykają problem, myślą: „Wiem, użyję perla”. Teraz mają problemy z $ (^ @ #% () ^%) (#).
Michael Hampton

4
@Jens, jeśli cokolwiek, dodatkowa moc PCRE w porównaniu do tradycyjnego wyrażenia regularnego sprawia, że ​​jest to bardziej kuszące rozwiązanie i trudniejsze do utrzymania. Skończone automaty, które dopasowuje PCRE, są eksplorowane w Rozszerzanie automatów skończonych, aby skutecznie pasowały do ​​wyrażeń regularnych zgodnych z Perl ... i jest to nie trywialna sprawa. Przynajmniej z tradycyjnym regex, można dostać głowę wokół niego bez zbyt wiele kłopotów raz niezbędne pojęcia są zrozumiałe.

6
Masz rację. Wyrażenia regularne są w rzeczywistości drugim, nietrywialnym językiem. Nawet jeśli oryginalny programista jest biegły w języku głównym i zastosowanym smaku wyrażeń regularnych, dodanie „drugiego języka” oznacza niższe szanse, które opiekunowie znają oba. Nie wspominając już o tym, że czytelność wyrażeń regularnych jest często niższa niż język „hosta”.
JS.

95

Wyrażenia regularne - szczególnie nietrywialne - są potencjalnie trudne do kodowania, zrozumienia i utrzymania. Wystarczy spojrzeć na liczbę pytań na temat przepełnienia stosu oznaczonych [regex]tam, gdzie pytający założył, że odpowiedź na ich problem jest wyrażeniem regularnym, a następnie utknęła. W wielu przypadkach problem można (i być może powinien) rozwiązać w inny sposób.

Oznacza to, że jeśli zdecydujesz się użyć wyrażenia regularnego, masz teraz dwa problemy:

  1. Oryginalny problem, który chciałeś rozwiązać.
  2. Wsparcie wyrażenia regularnego.

Zasadniczo myślę, że ma na myśli, że powinieneś używać wyrażenia regularnego tylko wtedy, gdy nie ma innego sposobu rozwiązania twojego problemu. Innym rozwiązaniem będzie prawdopodobnie łatwiejsze kodowanie, obsługa i obsługa. Może być wolniejszy lub mniej wydajny, ale jeśli nie jest to krytyczne, najważniejszą kwestią jest łatwość konserwacji i wsparcia.


27
Co gorsza: są wystarczająco potężne, aby oszukać ludzi, aby spróbowali użyć ich do analizy rzeczy, których nie potrafią, na przykład HTML. Zobacz liczne pytania na temat SO dotyczące „jak parsować HTML?”
Frank Shearar,

6
W niektórych sytuacjach wyrażenie regularne jest niesamowite. W wielu innych przypadkach nie tak bardzo. Z drugiej strony jest to przerażająca otchłań rozpaczy. Problem często pojawia się, gdy ktoś dowiaduje się o nich po raz pierwszy i zaczyna wszędzie widzieć aplikacje. Inne słynne powiedzenie: „Gdy jedynym narzędziem, jakie masz, jest młotek, wszystko wygląda jak gwóźdź”.
Todd Williamson,

3
Czy to oznacza, że ​​przez liczbę pytań w znaczniku SO [c #] jest to najtrudniejszy język programowania do zrozumienia?

2
Wolałbym raczej zobaczyć złożone wyrażenie regularne niż długą serię wywołań metod łańcuchowych. OTOH, naprawdę nie cierpię, gdy wyrażenia regularne są niewłaściwie używane do analizowania złożonych języków.
kevin cline

5
„Zasadniczo uważam, że ma na myśli, że powinieneś używać wyrażenia regularnego tylko wtedy, gdy nie ma innego sposobu rozwiązania twojego problemu. Każde inne rozwiązanie będzie łatwiejsze do kodowania, obsługi i wsparcia”. - poważnie się nie zgadzam .. Regeksy to doskonałe narzędzia, wystarczy znać ich granice. Wiele zadań można kodować bardziej elegancko za pomocą wyrażeń regularnych. (ale dla przykładu nie należy ich używać do analizowania kodu HTML)
Karoly Horvath,

69

Jest to przeważnie żart, choć z odrobiną prawdy.

Istnieje kilka zadań, dla których wyrażenia regularne są doskonale dopasowane. Kiedyś zastąpiłem 500 wierszy ręcznie napisanego kodu parsera rekurencyjnego zejścia jednym wyrażeniem regularnym, którego pełne debugowanie zajęło około 10 minut. Ludzie mówią, że wyrażenia regularne są trudne do zrozumienia i debugowania, ale odpowiednio zastosowane nie są tak trudne do debugowania, jak ogromny ręcznie zaprojektowany parser. W moim przykładzie debugowanie wszystkich najważniejszych przypadków rozwiązania nieregexowego zajęło dwa tygodnie.

Parafrazując wujka Bena:

Z wielką ekspresją wiąże się wielka odpowiedzialność.

Innymi słowy, wyrażenia regularne dodają ekspresji Twojemu językowi, ale nakłada na programistę większą odpowiedzialność za wybór najbardziej czytelnego trybu wyrażania dla danego zadania.

Niektóre rzeczy początkowo wyglądają na dobre zadanie dla wyrażeń regularnych, ale nimi nie są. Na przykład wszystko z zagnieżdżonymi tokenami, takie jak HTML. Czasami ludzie używają wyrażeń regularnych, gdy prostsza metoda jest bardziej przejrzysta. Na przykład string.endsWith("ing")jest łatwiejszy do zrozumienia niż odpowiednik wyrażenia regularnego. Czasami ludzie starają się wcisnąć duży problem w jeden regex, gdzie bardziej odpowiednie jest rozbicie go na kawałki. Czasami ludzie nie tworzą odpowiednich abstrakcji, powtarzając wielokrotnie wyrażenie regularne zamiast tworzyć dobrze nazwaną funkcję wykonującą to samo zadanie (być może zaimplementowaną wewnętrznie za pomocą wyrażenia regularnego).

Z jakiegoś powodu wyrażenia regularne mają dziwną tendencję do tworzenia martwego pola do normalnych zasad inżynierii oprogramowania, takich jak pojedyncza odpowiedzialność i DRY. Dlatego nawet ludzie, którzy je kochają, czasami uważają je za problematyczne.


10
Czy wujek Ben nie powiedział też „Doskonałe wyniki za każdym razem”? Może dlatego ludzie tak się cieszą z wyrażeń regularnych ...
Andrzej Doyle

4
Problem z wyrażeniami regularnymi dotyczącymi HTML, które wyzwalają niedoświadczonych programistów, polega na tym, że HTML ma gramatykę bezkontekstową, a nie regularną: wyrażenie regularne może być używane do niektórych prostych analiz składni HTML (lub XML) (np. Pobieranie adresu URL z nazwanego tagu anchor), ale nie nadaje się do niczego złożonego. W tym celu bardziej odpowiednie jest analizowanie DOM. Literatura pokrewna: Hierarchia Chomsky'ego .

53

Jeff Atwood przedstawia inną interpretację w poście na blogu, omawiając ten bardzo cytat: Wyrażenia regularne: teraz masz dwa problemy (dzięki Euphoric za link)

Analizując pełny tekst postów Jamiego w oryginalnym wątku z 1997 roku, znajdujemy następujące:

Natura Perla zachęca do używania wyrażeń regularnych prawie z wyłączeniem wszystkich innych technik; są zdecydowanie najbardziej „oczywistym” (przynajmniej dla ludzi, którzy nie znają lepszego) sposobem na przejście z punktu A do punktu B.

Pierwszy cytat jest zbyt pochlebny, aby można go było traktować poważnie. Ale całkowicie się z tym zgadzam. Oto, o czym Jamie starał się powiedzieć: nie to, że wyrażenia regularne są same w sobie złe, ale że nadużywanie wyrażeń regularnych jest złe.

Nawet jeśli nie w pełni zrozumieć wyrażeń regularnych, napotkasz The Golden Hammer problemu, próbując rozwiązać problem z wyrażeń regularnych, gdy byłoby łatwiejsze i bardziej jasne zrobić to samo z regularnym kodu (patrz również CodingHorror: Regex korzystania vs. nadużycie Regex ).

Istnieje inny post na blogu, który analizuje kontekst cytatu i jest bardziej szczegółowy niż Atwood: Blog Jeffrey'a Friedla: Źródło słynnego cytatu „Teraz masz dwa problemy”


3
Moim zdaniem jest to najlepsza odpowiedź, ponieważ dodaje kontekst. krytyka wyrażeń regularnych przez jwz dotyczyła zarówno Perla, jak i wszystkiego innego.
Evicatos

3
@Evicatos Przeprowadzono jeszcze więcej badań dotyczących tego samego wątku z 1997 r. W innym wpisie na blogu: regex.info/blog/2006-09-15/247
IQAndreas

30

Z tym cytatem dzieje się kilka rzeczy.

  1. Cytat jest powtórzeniem wcześniejszego żart:

    Za każdym razem, gdy napotyka problem, niektórzy mówią: „Użyjmy AWK”. Teraz mają dwa problemy. - D. Tilbrook

    Jest to żart i prawdziwe wykopalisko, ale także sposób na podkreślenie wyrażenia regularnego jako złego rozwiązania poprzez połączenie go z innymi złymi rozwiązaniami. To świetny ha ha tylko poważny moment.

  2. Dla mnie - pamiętam, ten cytat celowo jest otwarty na interpretację - znaczenie jest proste. Samo zapowiedź użycia wyrażenia regularnego nie rozwiązało problemu. Ponadto zwiększyłeś złożoność poznawczą kodu, dodając dodatkowy język z regułami, które różnią się od języka, którego używasz.

  3. Chociaż jest to zabawne jak żart, musisz porównać złożoność rozwiązania niebędącego wyrażeniem regularnym z złożonością rozwiązania wyrażenia regularnego + dodatkową złożonością dołączania wyrażeń regularnych. Być może warto rozwiązać problem z wyrażeniem regularnym, pomimo dodatkowych kosztów związanych z dodawaniem wyrażeń regularnych.


21

Wyrażenia regularne są teraz zestawem zwykłych rzeczy, które mają inną sformułowaną treść; w rzeczywistości istnieje prawdopodobieństwo, że jest to więcej niż ten element tekstu, ale niefortunnie, że mają one wpływ na powód, który powoduje pewne uzupełnienia.

(Wyrażenia regularne nie są gorsze do odczytania lub utrzymania niż jakakolwiek inna niesformatowana treść; rzeczywiście wyrażenie regularne jest prawdopodobnie łatwiejsze do odczytania niż ten fragment tekstu tutaj - ale niestety mają złą reputację, ponieważ niektóre implementacje nie pozwalają na formatowanie i ogólnie ludzi nie wiem, czy możesz to zrobić.)


Oto trywialny przykład:

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


Co tak naprawdę nie jest tak trudne do odczytania lub utrzymania, ale jest nawet łatwiejsze, gdy wygląda tak:

(?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

To trochę przesadzony przykład (komentowanie $jest podobne do komentowania i++), ale najwyraźniej nie powinno być problemu z czytaniem, rozumieniem i utrzymywaniem tego.


Tak długo, jak masz jasność, kiedy wyrażenia regularne są odpowiednie, a kiedy są złym pomysłem, nie ma w nich nic złego, a większość razy cytat JWZ tak naprawdę nie ma zastosowania.


1
Jasne, ale nie szukam dyskusji na temat zalet wyrażeń regularnych i nie chciałbym, aby ta dyskusja przebiegała w ten sposób. Próbuję zrozumieć, o co mu chodzi.
Paul Biggar

1
Następnie link w komentarzu livibetter mówi ci, co musisz wiedzieć. Ta odpowiedź wskazuje tylko, że wyrażenia regularne nie muszą być niejasne, a zatem cytat jest nonsensowny.
Peter Boughton,

8
Po co używać *+? Jak to się różni (funkcjonalnie) od sprawiedliwego *?
Timwi,

1
Chociaż to, co mówisz, może być prawdą, nie odpowiada na to konkretne pytanie. Twoja odpowiedź sprowadza się do: „moim zdaniem cytat zwykle nie jest prawdziwy”. Pytanie nie dotyczy tego, czy to prawda, czy nie, ale co oznacza cytat.
Bryan Oakley,

2
W *+tym przypadku dosłownie nie ma sensu ; wszystko jest zakotwiczone i może być dopasowane w jednym przejściu przez automat, który może liczyć do 22. Prawidłowy modyfikator w tych zestawach bez przecinków jest po prostu stary *. (Co więcej, tutaj nie powinno być różnic między chciwymi i niechcianymi algorytmami dopasowywania. Jest to niezwykle prosty przypadek.)
Donal Fellows

14

Oprócz odpowiedzi ChrisF - że wyrażenia regularne „są trudne do kodowania, rozumienia i utrzymywania”, jest jeszcze gorzej: są wystarczająco potężne, aby nakłonić ludzi do próby użycia ich do analizy rzeczy, których nie potrafią, na przykład HTML. Zobacz liczne pytania na temat SO dotyczące „jak parsować HTML?” Na przykład najbardziej epicka odpowiedź w całym SO!


14

Wyrażenia regularne są bardzo potężne, ale mają jeden mały i jeden duży problem; są trudne do napisania i prawie niemożliwe do odczytania.

W najlepszym przypadku użycie wyrażenia regularnego rozwiązuje problem, więc masz tylko problem z obsługą skomplikowanego kodu. Jeśli wyrażenie regularne nie jest odpowiednie, masz zarówno pierwotny problem, jak i problem z nieczytelnym kodem, który nie działa.

Czasami wyrażenia regularne są nazywane kodem tylko do zapisu. W obliczu wyrażenia regularnego, które wymaga naprawy, często szybciej jest zaczynać od zera niż próbować zrozumieć wyrażenie.


1
Prawdziwy problem polega na tym, że wyrażenia regularne nie mogą zaimplementować np. Parsera, ponieważ nie mogą policzyć, jak głęboko są zagnieżdżone.

4
@ Thorbjørn Ravn Andersen: To bardziej ograniczenie niż problem. Problem stanowi jedynie próba użycia do tego wyrażeń regularnych, a następnie nie jest to problem z wyrażeniami regularnymi, jest to problem z wyborem metody.
Guffa,

1
Możesz używać RE w porządku dla leksera (cóż, dla większości języków), ale składanie strumienia tokena w parsowanie drzewa (tj. Parsowanie ) jest formalnie poza nimi.
Donal Fellows,

10

Problem polega na tym, że regex jest skomplikowaną bestią, a problem rozwiązujesz tylko wtedy, gdy używasz regex doskonale. Jeśli tego nie zrobisz, będziesz mieć 2 problemy: twój oryginalny problem i regex.

Twierdzisz, że potrafi wykonać setkę wierszy kodu, ale możesz również argumentować, że 100 wierszy przejrzystego, zwięzłego kodu jest lepsze niż jeden wiersz wyrażenia regularnego.

Jeśli potrzebujesz na to dowodu: możesz sprawdzić ten SO Classic lub po prostu przeczesać tag SO Regex


8
Żadne z twierdzeń w pierwszym zdaniu nie jest prawdziwe. Regex nie jest szczególnie skomplikowany i jak żadne inne narzędzie nie musisz go doskonale znać, aby rozwiązywać z nim problemy. To tylko FUD. Twój drugi akapit jest po prostu absurdalny: oczywiście możesz argumentować. Ale to nie jest dobre.
Konrad Rudolph

1
@KonradRudolph Myślę, że fakt, że istnieje wiele narzędzi do generowania wyrażeń regularnych i sprawdzania poprawności, pokazuje, że wyrażenie regularne jest skomplikowanym mechanizmem. Nie jest czytelny dla człowieka (z założenia) i może spowodować całkowitą zmianę przepływu przez osobę modyfikującą lub piszącą fragment kodu, który używa wyrażenia regularnego. Co do drugiej części, myślę, że wynika to jasno z ogromnego grupowania wiedzy na temat P.SE i mówiąc: „Debugowanie kodu jest dwa razy trudniejsze niż jego pisanie, więc jeśli napiszesz najbardziej sprytny kod, jaki możesz, możesz z definicji nie są wystarczająco inteligentni, aby go debugować ”
Ampt

2
To nie jest właściwy argument. Tak, pewne wyrażenie regularne jest złożone. Ale i inne języki programowania. Regex jest znacznie mniej skomplikowany niż większość innych języków, a narzędzia istniejące dla regex są przyćmione przez narzędzia programistyczne dla innych języków (FWIW Pracuję intensywnie z regex i nigdy nie korzystałem z takich narzędzi…). Jest prostą prawdą, że nawet złożone wyrażenia regularne są prostsze niż równoważne nie-wyrażenia regularne.
Konrad Rudolph

@KonradRudolph Myślę, że mamy zasadniczą różnicę zdań co do definicji słowa „proste”. Dam ci, że wyrażenie regularne może być bardziej wydajne lub nawet bardziej wydajne, ale nie sądzę, że to proste słowo przychodzi do głowy, gdy myślisz o wyrażeniu regularnym.
Ampt

Być może robimy to, ale moja definicja jest możliwa do wykonania: rozumiem, że jest łatwy do zrozumienia, łatwy w utrzymaniu, mała liczba błędów ukrytych itp. Oczywiście złożone wyrażenie regularne na pierwszy rzut oka nie będzie bardzo zrozumiałe. Ale to samo dotyczy równoważnego fragmentu kodu niebędącego wyrażeniem regularnym. Nigdy nie mówiłem, że wyrażenie regularne jest proste. Mówię, że są prostsze - porównuję. To jest ważne.
Konrad Rudolph

7

Znaczenie składa się z dwóch części:

  • Po pierwsze, nie rozwiązałeś pierwotnego problemu.
    Prawdopodobnie odnosi się to do faktu, że wyrażenia regularne często oferują niepełne rozwiązania typowych problemów.
  • Po drugie, dodałeś teraz dodatkowe trudności związane z wybranym rozwiązaniem.
    W przypadku wyrażeń regularnych dodatkowa trudność prawdopodobnie odnosi się do złożoności, łatwości konserwacji lub dodatkowej trudności związanej z dopasowaniem wyrażeń regularnych do problemu, którego nie powinno się rozwiązać.

7

Gdy poprosisz o to w 2014 r., Interesujące byłoby skoncentrowanie się na ideologiach języków programowania w kontekście z 1997 r. W porównaniu do dzisiejszego kontekstu. Nie będę wchodził w tę debatę, ale opinie na temat Perla i samego Perla uległy znacznej zmianie.

Jednak, aby pozostać w kontekście z 2013 r. ( De l'eau a coulé sous les ponts depuis), sugerowałbym skupienie się na rekonstrukcji cytatów za pomocą słynnego komiksu XKCD, który jest bezpośrednim cytatem komiksu Jamiego Zawińskiego :

Komiks z XKCD o wyrażeniach regularnych, Perlu i problemach

Najpierw miałem problemy, aby zrozumieć ten komiks, ponieważ było to odniesienie do Zawinski cytatem, a cytat piosenki Jay-Z pieśnią, a odniesienie GNU program --help -zflagą 2 , tak, to było zbyt wiele kulturę mi to zrozumieć.

Wiedziałem, że to dobra zabawa, czułem to, ale tak naprawdę nie wiedziałem dlaczego. Ludzie często żartują na temat Perla i wyrażeń regularnych, zwłaszcza, że ​​nie jest to najmodniejszy język programowania, nie bardzo wiedzą, dlaczego to ma być zabawą ... Może dlatego, że manipulatorzy Perla robią głupie rzeczy .

Tak więc początkowy cytat wydaje się sarkastycznym żartem opartym na rzeczywistych problemach (ból?) Spowodowanych programowaniem za pomocą narzędzi, które boli. Tak jak młot może zranić murarza, programowanie za pomocą narzędzi, które nie są tymi, które wybrałby deweloper, gdyby mógł zranić (mózg, uczucia). Czasami zdarzają się wielkie debaty na temat tego, które narzędzie jest najlepsze, ale jest to prawie bezwartościowe, ponieważ jest to problem Twojego gustu lub gustu zespołu programistycznego , powodów kulturowych lub ekonomicznych . Kolejny doskonały komiks XKCD na ten temat:

Komiks z XKCD o debatach na temat narzędzi programistycznych

Rozumiem, że ludzie odczuwają ból związany z wyrażeniami regularnymi i wierzą, że inne narzędzie lepiej nadaje się do tego, do czego przeznaczone są wyrażenia regularne. Kiedy @ karl-bielefeldt odpowiada na twoje pytanie z wielką ekspresją, pojawia się wielka odpowiedzialność , a wyrażenia regularne są tym szczególnie zaniepokojone. Jeśli programista nie dba o to, jak s-on radzi sobie z wyrażeniami regularnymi, w końcu będzie to stanowić problem dla ludzi, którzy utrzymają kod później.

Kończę tę odpowiedzią na temat rekonstrukcji cytatów cytatem przedstawiającym typowy przykład z Perl Best Practices Damiana Conwego (książka z 2005 roku).

Wyjaśnia, że pisanie takiego wzoru:

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

... jest nie do przyjęcia bardziej niż napisanie takiego programu :

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<>;

Ale można go przepisać , wciąż nie jest ładny, ale przynajmniej można go przetrwać.

# 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

Ten rodzaj kodu w kształcie prostokąta jest drugim problemem, a nie wyrażeniami regularnymi, które można sformatować w jasny, łatwy do utrzymania i czytelny sposób.


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

Jeśli jest jedna rzecz, której powinieneś nauczyć się z informatyki, to hierarchia Chomsky'ego . Powiedziałbym, że wszystkie problemy z wyrażeniami regularnymi wynikają z prób parsowania gramatyki bezkontekstowej. Kiedy możesz narzucić limit (lub pomyśleć, że możesz narzucić limit) na poziomy zagnieżdżenia w CFG, otrzymasz te długie i złożone wyrażenia regularne.


1
Tak! Ludzie, którzy uczą się wyrażeń regularnych bez tej części tła CS, nie zawsze rozumieją, że są tylko niektóre rzeczy, których matematyczne wyrażenie regularne nie może zrobić.
benzado

5

Wyrażenia regularne są bardziej odpowiednie do tokenizacji niż do parsowania na pełną skalę.

Ale zaskakująco duży zestaw rzeczy, które programiści muszą przeanalizować, można przeanalizować za pomocą zwykłego języka (lub, co gorsza, można go prawie parsować za pomocą zwykłego języka i jeśli napiszesz tylko trochę więcej kodu ...).

Więc jeśli ktoś jest przyzwyczajony do „aha, muszę rozróżniać tekst, użyję wyrażenia regularnego”, łatwo jest zejść tą drogą, gdy potrzebujesz czegoś, co jest bliższe automatowi push-down, parserowi CFG lub nawet mocniejsze gramatyki. To zwykle kończy się łzami.

Więc myślę, że cytat nie jest tak trzaskającym wyrażeniem regularnym, mają swoje zastosowanie (i dobrze wykorzystane, są naprawdę bardzo przydatne), ale nadmierne poleganie na wyrażeniach regularnych (lub, w szczególności, ich bezkrytyczny wybór) .


3

jwz jest po prostu szalony z tym cytatem. wyrażenia regularne nie różnią się niczym od żadnej funkcji językowej - łatwe do spieprzenia, trudne do eleganckiego użycia, czasem mocne, czasem nieodpowiednie, często dobrze udokumentowane, często przydatne.

to samo można powiedzieć o arytmetyki zmiennoprzecinkowej, zamknięciach, orientacji obiektowej, asynchronicznych We / Wy lub cokolwiek innego, co można nazwać. jeśli nie wiesz, co robisz, języki programowania mogą cię zasmucić.

jeśli uważasz, że wyrażenia regularne są trudne do odczytania, spróbuj odczytać równoważną implementację analizatora składni w celu wykorzystania danego wzorca. często wyrażenia regularne wygrywają, ponieważ są bardziej zwarte niż pełne parsery ... aw większości języków są również szybsze.

nie zniechęcaj się do używania wyrażeń regularnych (lub jakiejkolwiek innej funkcji językowej), ponieważ autopromocyjny bloger wydaje niekwalifikowane oświadczenia. wypróbuj rzeczy dla siebie i sprawdź, co Ci odpowiada.


1
FWIW, arytmetyka zmiennoprzecinkowa jest o wiele trudniejsza niż RE, ale wydaje się prostsza. Strzec się! (Przynajmniej trudne RE wydają się być niebezpieczne.)
Donal Fellows,

3

Moja ulubiona, dogłębna odpowiedź na to pytanie została podana przez słynnego Roba Pike'a w poście na blogu skopiowanym z wewnętrznego komentarza Google: http://commandcenter.blogspot.ch/2011/08/regular-expressions-in-lexing- i.html

Podsumowując, nie jest tak, że są złe , ale często są używane do zadań, dla których niekoniecznie są odpowiednie, szczególnie jeśli chodzi o leksykację i analizę niektórych danych wejściowych.

Wyrażenia regularne są trudne do napisania, trudne do napisania i mogą być drogie w porównaniu z innymi technologiami ... Z drugiej strony Lexery są dość łatwe do napisania poprawnie (jeśli nie tak kompaktowo) i bardzo łatwe do przetestowania. Zastanów się nad znalezieniem alfanumerycznych identyfikatorów. Nie jest trudno napisać wyrażenie regularne (coś w stylu „[a-ZA-Z _] [a-ZA-Z_0-9] *”), ale naprawdę nie jest trudniej napisać jako prostą pętlę. Wydajność pętli będzie jednak znacznie wyższa i będzie wymagać znacznie mniej kodu pod okładkami. Biblioteka wyrażeń regularnych to wielka rzecz. Używanie jednego do parsowania identyfikatorów jest jak używanie Ferrari, aby przejść do sklepu po mleko.

Mówi o wiele więcej, argumentując, że wyrażenia regularne są przydatne np. W jednorazowym dopasowywaniu wzorców w edytorach tekstowych, ale rzadko powinny być używane w skompilowanym kodzie i tak dalej. Warto przeczytać.


0

Jest to związane z epigramem Alana Perlisa # 34:

Łańcuch jest surową strukturą danych i wszędzie tam, gdzie jest przekazywany, proces kopiowania jest bardzo duży. Jest to idealny pojazd do ukrywania informacji.

Jeśli więc wybierzesz ciąg znaków jako strukturę danych (i, oczywiście, kod oparty na wyrażeniach regularnych jako algorytmy do manipulowania nim), masz problem, nawet jeśli działa: zły projekt wokół niewłaściwej reprezentacji danych, który jest trudny do rozszerzyć i nieefektywne.

Jednak często to nie działa: pierwotny problem nie został rozwiązany, więc w takim przypadku masz dwa problemy.


0

Regeksy są szeroko stosowane do szybkiego i brudnego parsowania tekstu. Są doskonałym narzędziem do wyrażania wzorów, które są nieco bardziej złożone niż zwykłe dopasowanie ciągów.

Jednak, gdy wyrażenia regularne stają się coraz bardziej złożone, problemy serwerowe podnoszą głowę.

  1. Składnia wyrażeń regularnych jest zoptymalizowana pod kątem prostego dopasowywania, większość znaków pasuje do siebie. Jest to świetne w przypadku prostych wzorców, ale gdy skończy się więcej niż kilka poziomów zagnieżdżania, powstanie coś bardziej przypominającego szum linii niż dobrze skonstruowany kod. Myślę, że możesz napisać wyrażenie regularne jako serię połączonych ciągów znaków z wcięciami i komentarzami pomiędzy nimi, aby pokazać strukturę kodu, ale wydaje się, że tak się zdarza rzadko.
  2. Tylko niektóre typy dopasowywania tekstu są dobrze dopasowane do wyrażeń regularnych. Często zdarza się, że dostajesz szybki i brudny parser oparty na wyrażeniach regularnych dla pewnego rodzaju języka znaczników, ale potem próbujesz objąć więcej przypadków narożnych i okazuje się, że wyrażenia regularne stają się coraz bardziej złożone i coraz mniej czytelne
  3. Złożoność wyrażenia regularnego w czasie może nie być obvoius. Nie jest tak trudno skończyć z wzorcem, który działa świetnie, gdy pasuje, ale ma złożoność O (2 ^ n) w niektórych przypadkach niedopasowania .

Dlatego zbyt łatwo jest zacząć od problemu z przetwarzaniem tekstu, zastosować do niego wyrażenia regularne i skończyć z dwoma problemami, pierwotnym problemem, który próbowałeś rozwiązać i radzeniem sobie z wyrażeniami regularnymi, które próbujesz rozwiązać (ale nie rozwiązujesz poprawnie) oryginalny problem.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.