Podczas eksploracji wyrażeń regularnych (znanych również jako RegEx-es) istnieje wiele osób, które wydają się postrzegać wyrażenia regularne jako Świętego Graala. Coś, co wygląda na tak skomplikowane - po prostu musi być odpowiedzią na każde pytanie. Zwykle myślą, że każdy problem można rozwiązać za pomocą wyrażeń regularnych.
Z drugiej strony jest też wiele osób, które za wszelką cenę starają się unikać wyrażeń regularnych. Próbują znaleźć sposób na wyrażenie regularne i akceptują dodatkowe kodowanie, nawet jeśli wyrażenia regularne byłyby bardziej zwartym rozwiązaniem.
Dlaczego wyrażenia regularne są tak kontrowersyjne? Czy istnieją powszechne nieporozumienia dotyczące sposobu ich działania? Czy może być powszechne przekonanie, że wyrażenia regularne są na ogół powolne?
Odpowiedzi:
Nie sądzę, by ludzie sprzeciwiali się wyrażeniom regularnym, ponieważ są powolni, ale raczej dlatego, że trudno je czytać i pisać, a także trudne do poprawnego działania. Chociaż istnieją sytuacje, w których wyrażenia regularne zapewniają skuteczne, kompaktowe rozwiązanie problemu, czasami są one wykorzystywane w sytuacjach, w których lepiej jest zamiast tego użyć łatwej do odczytania, łatwej do utrzymania sekcji kodu.
źródło
|
lub.*
), ponieważ używają maszyny stosu i śledzenia wstecznego. Dlatego musisz dokładnie dostroić swoje wyrażenia regularne w Perlu, Javie, Pythonie, Ruby… Starym stylu silniki wyrażeń regularnych (grep
na przykład) najpierw kompilują wzór do DFA. Następnie złożoność wzoru jest w dużej mierze nieistotna. Właśnie użyłem Java i grep dla tego samego tekstu i wzoru: 22min vs 2s. Oto nauka: swtch.com/~rsc/regexp/regexp1.htmlUtrzymywanie regeksów w utrzymaniu
Znaczącym postępem w kierunku odszyfrowania wzorców zwanych wcześniej „wyrażeniami regularnymi” jest
/x
flaga wyrażeń regularnych Perla - czasami zapisywana(?x)
po osadzeniu - która umożliwia spacje (łamanie linii, wcięcia) i komentarze. To znacznie poprawia czytelność, a tym samym łatwość konserwacji. Biała przestrzeń pozwala na dzielenie kognitywne, dzięki czemu można zobaczyć, z którymi grupami co.Współczesne wzorce obsługują teraz zarówno relatywnie ponumerowane, jak i nazwane odwołania wsteczne. Oznacza to, że nie musisz już liczyć grup przechwytywania, aby dowiedzieć się, że potrzebujesz
$4
lub\7
. Pomaga to w tworzeniu wzorów, które można uwzględnić w kolejnych wzorach.Oto przykład względnie numerowanej grupy przechwytywania:
A oto przykład lepszego podejścia do nazwanych chwytów:
Reguły gramatyczne
Co najważniejsze , te nazwane zrzuty można umieścić w
(?(DEFINE)...)
bloku, dzięki czemu można oddzielić deklarację od wykonania poszczególnych nazwanych elementów wzorców. To sprawia, że zachowują się one jak podprogramy we wzorcu.Dobry przykład tego rodzaju „wyrażenia gramatycznego” można znaleźć w tej i tej odpowiedzi . Wyglądają one bardziej jak deklaracja gramatyczna.
Jak to ostatnie przypomina:
Tego nie można przecenić. Oczywiście, jeśli nie użyjesz tych rzeczy w swoich wzorach, często stworzysz koszmar. Ale jeśli zrobić z nich korzystać, choć nie musisz.
Oto kolejny przykład nowoczesnego wzorca gramatycznego, ten do analizowania RFC 5322: użyj 5.10.0;
Czy to nie jest niezwykłe - i wspaniałe? Możesz wziąć gramatykę w stylu BNF i przetłumaczyć ją bezpośrednio na kod bez utraty podstawowej struktury!
Jeśli nowoczesne wzorce gramatyczne nadal nie są dla Ciebie wystarczające, genialny
Regexp::Grammars
moduł Damiana Conwaya oferuje jeszcze czystszą składnię, a także doskonałe debugowanie. Oto ten sam kod do analizowania przekształcenia RFC 5322 we wzorzec z tego modułu:Jest wiele dobrych rzeczy w perlre podręcznika , ale te dramatyczne zmiany w podstawowych cech konstrukcyjnych regex są w żaden sposób ograniczone do Perl sam. Rzeczywiście pcrepattern podręcznika może być łatwiejszy do odczytu i obejmuje ten sam obszar.
Nowoczesne wzorce nie mają prawie nic wspólnego z prymitywnymi rzeczami, których nauczyłeś się w swojej klasie automatów skończonych.
źródło
/x
. Korzysta z wyrażeń gramatycznych, z(?&name)
wewnętrznymi podprogramami wyrażeń regularnych, które naprawdę sprawiają, że to błyszczy.re.VERBOSE
flagę.Regeksy to świetne narzędzie, ale ludzie myślą: „Hej, co za wspaniałe narzędzie, użyję go do robienia X!” gdzie X jest czymś, do czego lepsze jest inne narzędzie (zwykle parser). Jest to standard przy użyciu młotka, w którym potrzebny jest problem ze śrubokrętem.
źródło
split($pattern,$string)
kontraexplode($delimiter,$string)
- na szczęście ten pierwszy się deprecjonuje, ale wiele kodu używało tego pierwszego, gdy potrzebowały tylko mocy późniejszego. Zrozumiałe, RegEx zapewnia łatwe narzędzie do robienia pewnych rzeczy, ale chyba, że potrzebujesz pełnej mocy wyrażeń regularnychPrawie wszyscy, których znam, którzy regularnie używają wyrażeń regularnych (zamierzone słowa kluczowe) pochodzą z uniksowego środowiska, w którym używają narzędzi, które traktują RE jako najwyższej klasy konstrukcje programistyczne, takie jak grep, sed, awk i Perl. Ponieważ prawie nie ma narzutu składniowego, aby użyć wyrażenia regularnego, ich wydajność znacznie wzrasta.
Natomiast programiści używający języków, w których RE są biblioteką zewnętrzną, zwykle nie zastanawiają się, co wyrażenia regularne mogą przynieść do tabeli. „Koszt czasu” programisty jest tak wysoki, że albo a) RE nigdy nie pojawiły się w ramach szkolenia, lub b) nie „myślą” w kategoriach RE i wolą polegać na bardziej znanych wzorcach.
źródło
Wyrażenia regularne pozwalają napisać niestandardową maszynę skończoną (FSM) w kompaktowy sposób, aby przetworzyć ciąg danych wejściowych. Istnieją co najmniej dwa powody, dla których używanie wyrażeń regularnych jest trudne:
Oldschoolowe tworzenie oprogramowania wymaga planowania, modeli papierowych i dokładnego przemyślenia. Wyrażenia regularne bardzo dobrze pasują do tego modelu, ponieważ prawidłowe napisanie skutecznego wyrażenia wymaga dużo wpatrzenia się w niego, wizualizacji ścieżek FSM.
Współcześni programiści woleliby raczej wykuć kod i użyć debuggera do wykonania zadania, aby sprawdzić, czy kod jest poprawny. Wyrażenia regularne nie obsługują tego stylu pracy zbyt dobrze. Jeden „ciąg” wyrażenia regularnego jest w rzeczywistości operacją atomową. Trudno zaobserwować stopniowe wykonywanie w debuggerze.
Zbyt łatwo jest napisać wyrażenie regularne, które przypadkowo akceptuje więcej danych wejściowych, niż zamierzają. Wartość wyrażenia regularnego nie jest tak naprawdę zgodna z prawidłowymi danymi wejściowymi, ale nie może być zgodna z nieprawidłowymi danymi wejściowymi . Techniki przeprowadzania „testów ujemnych” dla wyrażeń regularnych nie są bardzo zaawansowane lub przynajmniej nie są szeroko stosowane.
Do tego stopnia, że wyrażenia regularne są trudne do odczytania. Samo spojrzenie na wyrażenie regularne wymaga dużej koncentracji, aby wizualizować wszystkie możliwe dane wejściowe, które należy odrzucić, ale są błędnie akceptowane. Czy kiedykolwiek próbowałeś debugować kod wyrażenia regularnego innej osoby ?
Jeśli dzisiaj wśród programistów występuje opór przed używaniem wyrażeń regularnych, myślę, że wynika to głównie z tych dwóch czynników.
źródło
Ludzie myślą, że wyrażenia regularne są trudne; ale to dlatego, że źle ich używają. Pisanie złożonych jedno-liniowych tekstów bez komentarzy, wcięć i nazwanych ujęć. (Nie wciskasz złożonego wyrażenia SQL w jednym wierszu, bez komentarzy, wcięć i aliasów, prawda?). Tak, dla wielu ludzi nie mają sensu.
Jeśli jednak Twoja praca ma coś wspólnego z analizowaniem tekstu (z grubsza jakąkolwiek aplikacją internetową ...) i nie znasz wyrażeń regularnych, ssiesz swoją pracę i marnujesz swój czas i swoje pracodawca. Istnieją doskonałe zasoby , aby nauczyć Cię wszystkiego na ich temat, o których kiedykolwiek będziesz musiał wiedzieć, i wiele więcej.
źródło
x
modyfikator wyrażeń regularnych, który powoduje ignorowanie białych znaków. Umożliwia to umieszczenie wyrażenia regularnego w kilku wierszach i dodawanie komentarzy.re.X
akare.VERBOSE
.x
modyfikator w tcl. Uważam, że jest to dość standardowe, ponieważ tcl, w przeciwieństwie do innych języków, nie używa PCRE.Ponieważ brakuje najpopularniejszego narzędzia do nauki w powszechnie akceptowanych IDE: nie ma Kreatora Regex. Nawet autouzupełnianie. Musisz sam wszystko zakodować.
źródło
()
, kwadratowych[]
lub kręconych{}
. Działa również z odwrotnym ukośnikiem.„ Wyrażenia regularne: teraz masz dwa problemy ” to świetny artykuł na ten temat autorstwa Jeffa Atwooda. Zasadniczo wyrażenia regularne są „trudne”! Mogą tworzyć nowe problemy. Są jednak skuteczne.
źródło
Nie sądzę, żeby były tak kontrowersyjne.
Myślę również, że odpowiedziałeś na swoje własne pytanie, ponieważ wskazujesz, jak głupio byłoby używać ich wszędzie ( nie wszystko to zwykły język 2 ) lub w ogóle ich unikać. Ty, programista, musisz podjąć inteligentną decyzję, kiedy wyrażenia regularne pomogą kodowi lub go zranią. W obliczu takiej decyzji dwie ważne rzeczy, o których należy pamiętać, to łatwość utrzymania (co oznacza czytelność) i rozszerzalność.
Dla tych, którzy są im szczególnie niechętni, domyślam się, że nigdy nie nauczyli się ich właściwie używać. Myślę, że większość ludzi, którzy spędzą zaledwie kilka godzin na przyzwoitym samouczku, zrozumie je i bardzo szybko zacznie mówić. Oto moja sugestia, od czego zacząć:
http://docs.python.org/howto/regex
Chociaż ta strona mówi o wyrażeniach regularnych w kontekście Pythona, zauważyłem, że informacje te są bardzo przydatne gdzie indziej. Jest kilka rzeczy specyficznych dla Pythona, ale uważam, że są one wyraźnie odnotowane i łatwe do zapamiętania.
źródło
Wyrażenia regularne odnoszą się do ciągów znaków, którymi są operatory arytmetyczne do liczb, i nie uważałbym ich za kontrowersyjne. Myślę, że nawet dość apodyktyczny działacz OO , taki jak ja (który miałby tendencję do wybierania innych obiektów zamiast strun), byłby trudny do odrzucenia.
źródło
Problem polega na tym, że wyrażenia regularne są potencjalnie tak potężne, że możesz z nimi robić różne rzeczy, do których powinieneś użyć czegoś innego.
Dobry programista powinien wiedzieć, gdzie ich używać, a gdzie nie. Typowym przykładem jest parsowanie języków nieregularnych (zobacz Decydowanie, czy język jest prawidłowy ).
Myślę, że nie możesz się pomylić, jeśli najpierw ograniczysz się do prawdziwych wyrażeń regularnych (bez rozszerzeń). Niektóre rozszerzenia mogą uczynić swoje życie trochę łatwiejsze, ale jeśli znajdziesz coś trudno wyrazić jako prawdziwego regex, to może okazać się wskazanie, że regex nie jest odpowiednim narzędziem.
źródło
Równie dobrze możesz zapytać, dlaczego goto są kontrowersyjne.
Zasadniczo, kiedy masz tyle „oczywistej” mocy, ludzie są skłonni do nadużywania ich w sytuacjach, w których nie są najlepszym rozwiązaniem. Na przykład liczba osób, które proszą o parsowanie CSV, XML lub HTML w wyrażeniach regularnych, zaskakuje mnie. To nieodpowiednie narzędzie do pracy. Ale niektórzy użytkownicy i tak nalegają na stosowanie wyrażeń regularnych.
Osobiście staram się znaleźć to szczęśliwe medium - używaj wyrażeń regularnych do tego, do czego są dobre, i unikaj ich, gdy nie są optymalne.
Pamiętaj, że wyrażenia regularne mogą być nadal używane do analizowania plików CSV, XML, HTML itp. Ale zwykle nie w jednym wyrażeniu regularnym.
źródło
Nie sądzę, by „kontrowersyjne” było właściwym słowem.
Ale widziałem mnóstwo przykładów, w których ludzie mówią „jakie jest regularne wyrażenie, że muszę wykonywać takie i takie manipulacje ciągiem znaków?” które są problemami XY.
Innymi słowy, zaczęli od założenia, że regex jest tym, czego potrzebują, ale lepiej byłoby z split (), tłumaczeniem takim jak tr /// perla, w którym znaki są zastępowane jeden za drugim, lub tylko indeks ().
źródło
To interesujący temat.
Wielu miłośników wyrażeń regularnych wydaje się mylić zwięzłość formuły z wydajnością.
Co więcej, wyrażenie regularne, które wymaga wiele przemyślenia, daje autorowi ogromną satysfakcję, dzięki czemu jest od razu uzasadnione.
Ale ... wyrażenia regularne są tak wygodne, gdy wydajność nie stanowi problemu i musisz szybko poradzić sobie z tekstem, na przykład w Perlu. Ponadto, podczas gdy wydajność jest problemem, można nie próbować bić biblioteki regexp za pomocą domowego algorytmu, który może być wadliwy lub mniej wydajny.
Poza tym istnieje wiele powodów, dla których wyrażenia regularne są niesprawiedliwie krytykowane, na przykład
źródło
To, co myślę, to nauka regexu i utrzymywanie wyrażeń regularnych w niepopularnych, większość programistów jest leniwa lub większość z nich polega na bibliotekach zewnętrznych, aby zrobić dla nich analizę ... polegają na wyszukiwarce Google, a nawet pytają na forach pełny kod ich problemu. Ale jeśli chodzi o wdrożenie lub modyfikację / utrzymanie wyrażenia regularnego, po prostu zawodzą.
Istnieje popularne powiedzenie „Znajomi nie pozwalają znajomym używać Regex do analizowania HTML”
Ale jeśli o mnie chodzi, stworzyłem pełne parsery HTML przy użyciu Regex i uważam, że regex lepiej parsuje ciągi HTML zarówno pod względem szybkości, jak i pamięci (jeśli masz pomysł, co masz osiągnąć :))
źródło
Wyrażenia regularne są poważną tajemnicą dla wielu ludzi, w tym dla mnie. Działa świetnie, ale to tak, jakby patrzeć na równanie matematyczne. Z przyjemnością informuję, że ktoś w końcu stworzył skonsolidowaną lokalizację różnych funkcji wyrażeń regularnych na http://regexlib.com/ . Teraz, jeśli Microsoft utworzy tylko klasę wyrażeń regularnych, która automatycznie wykona większość typowych czynności, takich jak eliminacja liter lub filtrowanie dat.
źródło
Czasami uważam, że wyrażenia regularne są bezcenne. Kiedy muszę wykonać pewne „rozmyte” wyszukiwania i być może zastąpię je. Gdy dane mogą się różnić i mieć pewną losowość. Jednak gdy muszę wykonać proste wyszukiwanie i zamienić lub sprawdzić ciąg znaków, nie używam wyrażeń regularnych. Chociaż znam wielu ludzi, którzy to robią, używają go do wszystkiego. To jest kontrowersja.
Jeśli chcesz umieścić hals w ścianie, nie używaj młotka. Tak, zadziała, ale zanim zdobędziesz młot, mógłbym włożyć 20 haczyków w ścianę.
Wyrażeń regularnych należy używać do tego, do czego zostały zaprojektowane, i nic więcej.
źródło
Chociaż myślę, że wyrażenia regularne są niezbędnym narzędziem, najbardziej denerwujące jest to, że istnieją różne implementacje. Nieznaczne różnice w składni, modyfikatorach, a zwłaszcza „chciwości” mogą sprawić, że wszystko stanie się naprawdę chaotyczne, wymagające prób i błędów, a czasem generowania zagadkowych błędów.
źródło
W niektórych przypadkach myślę, że MUSISZ ich użyć. Na przykład, aby zbudować leksykon.
Moim zdaniem jest to punkt widzenia ludzi, którzy potrafią pisać wyrażenia regularne i ludzi, którzy nie (lub prawie nie). Osobiście uważam, że dobrym pomysłem jest na przykład sprawdzenie poprawności formularza, czy to w javascript, aby ostrzec użytkownika, czy w języku po stronie serwera.
źródło
Myślę, że jest to mniej znana technika wśród programistów. Zatem nie ma na to szerokiej akceptacji. A jeśli masz nietechnicznego managera do przeglądu kodu lub pracy, wyrażenie regularne jest bardzo złe. Spędzisz godziny na pisaniu idealnego wyrażenia regularnego i dostaniesz niewiele ocen za moduł, myśląc, że napisał tak mało wierszy kodu. Ponadto, jak powiedziano w innym miejscu, czytanie wyrażeń regularnych jest bardzo trudnym zadaniem.
źródło
Przyzwoite systemy wyrażeń regularnych, takie jak używane w lex i yacc do definicji kompilatora, są dobre, bardzo przydatne i czyste. W tych systemach typy wyrażeń są zdefiniowane w kategoriach innych. To ohydne zniekształcone, nieczytelne gigantyczne wyrażenia regularne z jednym wierszem, powszechnie spotykane w kodzie perl i sed (itp.), Które są „kontrowersyjne” (śmieci).
źródło
Najlepsze prawidłowe i normalne użycie wyrażenia regularnego to sprawdzanie poprawności formatu adresu e-mail.
To dobre zastosowanie.
Używałem wyrażeń regularnych niezliczoną ilość razy jako jednorazowy efekt w TextPad do masowania płaskich plików, tworzenia plików csv, tworzenia instrukcji wstawiania SQL i tego typu rzeczy.
Dobrze napisane wyrażenia regularne nie powinny być zbyt wolne. Zwykle alternatywy, takie jak mnóstwo wezwań do zamiany, są znacznie wolniejszymi opcjami. Równie dobrze może to zrobić za jednym razem.
Wiele sytuacji wymaga wyrażeń regularnych i nic więcej.
Kolejnym dobrym zastosowaniem jest zastąpienie specjalnych znaków niedrukowalnych znakami nieszkodliwymi.
Mogę oczywiście wyobrazić sobie, że istnieją pewne podstawy kodowe, które nadużywają wyrażeń regularnych ze szkodą dla łatwości obsługi. Sam nigdy tego nie widziałem. Recenzenci kodu naprawdę mnie uprzedzili za to, że nie używają wystarczająco wyrażeń regularnych.
źródło