Чому регулярні вирази настільки суперечливі? [зачинено]


212

Під час вивчення регулярних виразів (інакше відомих як RegEx-es) є багато людей, які, здається, бачать регулярні вирази як Святий Грааль. Щось, що виглядає так складно - просто має бути відповіддю на будь-яке питання. Вони схильні думати, що кожна проблема вирішується за допомогою регулярних виразів.

З іншого боку, також є багато людей, які намагаються уникнути регулярних висловів за будь-яку ціну. Вони намагаються знайти шлях навколо регулярних виразів і прийняти додаткове кодування саме заради нього, навіть якщо регулярні вирази були б більш компактним рішенням.

Чому регулярні вирази вважаються настільки суперечливими? Чи є поширені непорозуміння щодо того, як вони працюють? Чи може бути поширена думка, що регулярні вирази, як правило, повільні?


9
якщо це дискусія, то чи не слід її закривати? але я бачу справжнє питання там, тож, можливо, тег обговорення не належить?
RCIX

6
Без жартів. Ви виховуєте це, і люди починають тут усе божеволіти.
Райан Флоренція

1
Приємного спостереження та формулювання у питанні!
imz - Іван Захарящев


Питання, засноване на думці, і тут має застосовуватися правило (або питання слід редагувати, щоб надати точну відповідь). Це сказав, що я припускаю, що суперечки щодо регулярних виразів випливають з неточності навчальних посібників та посібників з цього приводу. Більшість випадків, якщо не весь час інформація змішується, і крім того, нам не даються всі характеристики. Додайте до цієї помилки використання мови, ви в кінці кінців навчитесь щось помічати в дорозі, що це може означати щось інше. І нарешті, спеціальні символи регулярного виразів не обмежуються одним значенням, яке додає більше плутанини.
intika

Відповіді:


136

Я не думаю, що люди заперечують проти регулярних виразів тому, що вони повільні, а швидше тому, що їх важко читати і писати, а також складні, щоб правильно вийти. Хоча є деякі ситуації, коли регулярні вирази забезпечують ефективне, компактне вирішення проблеми, вони іноді підпадають під ситуацію, коли краще замість цього використовувати легкий для читання роздільний код.


2
І так, регулярні вирази можуть бути надзвичайно повільними порівняно з використанням простих функцій. І не просто повільно, але продуктивність двигуна регулярного випромінювання може бути абсолютно непередбачуваною, якщо стикатися з довільними (наданими користувачем) входами.
Pacerier

1
Якщо ви знаєте, як працює гегекс, це зовсім не проблема.
Шиплу Мокаддім

8
@pacerier, це не повільні схеми , це повільні двигуни . Більшість (сучасних) двигунів регулярної експресії непридатні для складних моделей (наприклад, багато |або .*), оскільки вони використовують стек-машину і зворотний трекінг. Ось чому ви повинні ретельно налаштувати свої регулярні вирази в Perl, Java, Python, Ruby… Двигуни регулярного вираження старого стилю ( grepнаприклад, наприклад) спочатку компілюють шаблон у DFA. Згодом складність схеми значною мірою не має значення. Я щойно використовував Java та grep для того ж тексту та шаблону: 22 хв проти 2 с. Ось наука: swtch.com/~rsc/regexp/regexp1.html
hagello

122

Зробити регулярні регекси

Основним кроком у напрямку демістифікації шаблонів, які раніше називались "регулярними виразами", є /xпрапорець регулярного виразів Perl, який іноді пишеться (?x)під час вбудовування, що дозволяє пробілити пробіл (розрив рядків, відступ) та коментарі. Це серйозно покращує читабельність і, отже, ремонтопридатність. Білий простір дозволяє здійснювати когнітивне чування, тож ви можете бачити, з якими групами.

Сучасні зразки також тепер підтримують як відносно пронумеровані, так і названі зворотні посилання. Це означає, що вам більше не потрібно рахувати групи захоплення, щоб зрозуміти, що вам потрібно $4чи \7. Це допомагає створювати візерунки, які можна включити до подальших зразків.

Ось приклад відносно пронумерованої групи захоплення:

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

Ось приклад вищого підходу названих захоплень:

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

Граматичні реджекси

Найкраще , що ці названі захоплення можна розмістити всередині (?(DEFINE)...)блоку, щоб ви могли відокремити декларацію від виконання окремих названих елементів ваших шаблонів. Це змушує їх діяти швидше як підпрограми в рамках шаблону.
Хороший приклад подібного роду «граматичного виразів» можна знайти у цій відповіді та в цій . Вони набагато більше схожі на граматичну декларацію.

Як останній нагадує вам:

… Переконайтеся, що ніколи не записуйте шаблони ліній-шуму. Вам не потрібно, і ви не повинні. Жодна мова програмування не може бути досяжною, що забороняє пробіл, коментарі, підпрограми або буквено-цифрові ідентифікатори. Тому використовуйте всі ті речі у своїх моделях.

Це не можна перебільшувати. Звичайно, якщо ви не використовуєте ці речі у своїх моделях, ви часто створюєте кошмар. Але якщо ви робите їх використовувати, хоча, вам не потрібно.

Ось ще один приклад сучасного граматичного малюнка, цей для розбору RFC 5322: використовуйте 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;

Хіба це не примітно - і чудово? Ви можете взяти граматику в стилі BNF і перекласти її безпосередньо в код, не втрачаючи своєї фундаментальної структури!

Якщо сучасних граматичних зразків все ще недостатньо для вас, то геніальний Regexp::Grammarsмодуль Даміана Конвея пропонує ще більш чистий синтаксис і з чудовою налагодженням. Ось той самий код для розбору RFC 5322, переробленого на шаблон із цього модуля:

#!/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
    }
}

Там дуже багато хороших речей в perlre сторінка керівництва , але ці значні поліпшення в основних регулярних виразів конструктивних особливостей аж ніяк не обмежується Perl в поодинці. Дійсно pcrepattern сторінка керівництва може бути легше читати, і охоплює ту ж територію.

Сучасні зразки майже нічого спільного не мають із примітивними речами, яких ви навчали у вашому кінцевому класі автоматичних програм.


9
ТАК! ТАК! Нарешті, хтось показує чудовий приклад того, наскільки читабельні регулярні вирази можуть бути з модифікатором x. Я не можу повірити, як мало хто знає, що воно існує, не кажучи вже про те, що насправді ним користується.
Шабіроб

1
@Shabbyrobe: Це не просто /x. Це використання режексів граматично, з (?&name)внутрішніми підпрограмами регулярного виведення, що дійсно робить цей блиск.
tchrist

+1 Ви завжди дізнаєтесь щось нове. Я не знав, що PCRE має "хибну" умову для визначень.
NikiC

5
У Python аналогічно є re.VERBOSEпрапор.
Механічний равлик

3
Просто гунна йти вперед і сказати, що я все ще дивуюся тому, наскільки люди будуть йти, щоб зробити регулярний вимір.
Слейтер Вікторофф

68

Реджекси - це чудовий інструмент, але люди думають: "Ей, який чудовий інструмент, я використаю його, щоб зробити X!" де X - це те, для чого краще використовувати інший інструмент (як правило, аналізатор). Це стандарт із застосуванням молотка, де вам потрібна проблема з викруткою.


4
Пам'ятайте лише, що більшість аналізаторів -алексичні аналізатори все ще використовують регулярні вирази для розбору своїх речей :-)
Джаспер Беккерс

62
Скажімо, що парсери використовують регулярні вирази - це як сказати, що парсери використовують оператори призначення. Це нічого не означає, поки ви не подивитеся, щоб побачити, як вони використовуються.
Час. Овенс

24
Використання RegEx, коли аналізатор кращий, дратує. Використання RegEx, коли стандартні функції пошуку або заміни рядків мови будуть працювати (і в лінійний час, як правило), просто недоцільно.
jmucchiello

1
Погоджено, тому що RegEx має бути джеком для всіх торгів, які він обробляє накладними, величезний. Тільки тому, що використання двигуна RegEx здається простим, не означає, що це краще рішення над ітераційним аналізатором (поріг, який залежить від розробника). Один з моїх улюблених прикладів split($pattern,$string)проти PHP explode($delimiter,$string)- на щастя, колишній знецінюється, але багато коду використовували перший, коли їм потрібна була потужність лише пізнішої. Погоджений, RegEx надає простий інструмент для виконання деяких справ, але якщо вам не потрібна
вся

4
Лексичні аналізатори дійсно можуть використовувати регулярні вирази. Вони також відомі як токенізатори, але вони не є синтаксичними аналізаторами (або аналізаторами). Для читання досить складного рядка слід використовувати токенізатор, щоб прочитати рядок як лексеми (можливо, з регулярними виразами, можливо, ні, залежно від токенізатора). Ці лексеми повинні бути передані в аналізатор, який буде обробляти їх граматичними правилами, які точно не є регулярними виразами.
Аксель

53

Майже всі, кого я знаю, хто регулярно використовує регулярні вирази (призначені для каламбурів), походять з фонових зображень Unix, де вони використовують інструменти, які розглядають REs як першокласні конструктивні програми, такі як grep, sed, awk та Perl. Оскільки майже немає синтаксичних накладних даних, щоб використовувати регулярний вираз, їх продуктивність збільшується вгору, коли вони є.

На відміну від цього, програмісти, які використовують мови, в яких RE є зовнішньою бібліотекою, як правило, не враховують, які регулярні вирази можуть внести до таблиці. Програміст "витрати часу" настільки високий, що або а) РЕ ніколи не з'являлися в рамках своєї підготовки, або б) вони не "думають" з точки зору РЕ і вважають за краще відмовитися від більш звичних моделей.


11
Так, я ніколи не пробачив Python за те, що він робив синтаксис синтаксису регулярних виразів за допомогою бібліотеки. Я думаю, що це чистота над розумом.
slikts

7
Я походжу з фонових зображень Unix, використовував sed, awk & perl завантаження, і, звичайно, робив багато поздоровлень, але знайте, що коли я використовую регулярний вираз, це хак лише для запису, який я ненавиджу підтримувати. Це добре для скриптів оболонок / одноразових, але для реальної роботи, для всього, що не є просто захопленням-деякими-даними-для збереження-зараз, я зараз використовую належний токенізатор / лексер / аналізатор з чітким синтаксисом. Мій улюблений робить все / будь-яке, чисто + може самооптимізуватися. Я навчився важкому шляху, і протягом багатьох років, що трохи самодисципліни на старті означає менше зусиль пізніше. Зворотний вираз - це момент на клавіатурі, а життя - на хмурість.
AndrewC

44

Регулярні вирази дозволяють написати компактну машину з кінцевим станом (FSM) компактним способом, щоб обробити рядок введення. Принаймні дві причини, чому використовувати регулярні вирази важко:

  • Розробка програмного забезпечення для старої школи передбачає багато планування, паперових моделей та ретельної думки. Регулярні вирази дуже добре вписуються в цю модель, тому що правильно писати ефективний вираз передбачає багато дивлячись на нього, візуалізуючи шляхи FSM.

    Сучасні розробники програмного забезпечення краще скористатися кодом і використовувати відладчик, щоб перейти до виконання, щоб побачити, чи правильний код. Регулярні вирази не дуже добре підтримують цей стиль роботи. Один "запуск" регулярного виразу - це фактично атомна операція. Важко спостерігати поетапне виконання у відладчику.

  • Надто просто написати регулярний вираз, який випадково сприймає більше вводу, ніж ви плануєте. Значення регулярного виразу насправді не відповідає дійсному вводу, воно не відповідає недійсному вводу . Техніки робити "негативні тести" для регулярних виразів не дуже вдосконалені або, принаймні, не широко використовуються.

    Це доходить до того, що регулярні вирази важко читати. Просто дивлячись на регулярний вираз, потрібно багато концентрації, щоб візуалізувати всі можливі дані, які слід відхилити, але помилково прийняти. Завжди намагаються налагодити хто - то чужий звичайний код вираження?

Якщо сьогодні серед розробників програмного забезпечення існує стійкість до використання регулярних виразів, я думаю, що це пов'язано головним чином з цими двома чинниками.


4
Є відмінні інструменти для налагодження regexps
Jasper Bekkers

15
perl -Mre = debug -e "q [aabbcc] = ~ / ab * [cd] /"
Бред Гілберт

15
Я не думаю, що я коли-небудь можу побачити абревіатуру "FSM", не замислюючись про Літаюче чудовисько спагетті.
Шабіроб

4
@Shabbyrobe: Я не хочу ображати. За бажанням ви можете використовувати детермінований кінцевий автомат (DFA).
Білл Карвін

37

Люди схильні думати, що регулярні вирази важкі; але це тому, що вони неправильно їх використовують. Написання складних однокласників без жодних коментарів, відступів або названих захоплень. (Ви не стискаєте свій складний вираз SQL в одному рядку без коментарів, відступів чи псевдонімів, чи не так?). Так що так, для багатьох людей вони не мають сенсу.

Однак якщо ваша робота має щось спільне з розбором тексту (приблизно будь-який веб-додаток там ...), і ви не знаєте регулярного вираження, ви смокчуть свою роботу, і ви витрачаєте свій власний час і час свого роботодавця. Там є чудові ресурси , щоб навчити вас усьому про них, що вам коли-небудь потрібно знати, та багато іншого.


2
Ну .. різниця полягає в тому, що декілька пробілів мають значення в регулярному вираженні, де в інших мовах цього немає, і тому вони, як правило, є одними вкладишами (які іноді переходять на кілька рядків :)
Радо

14
@Rado: Наприклад, Perl має xмодифікатор для регулярних виразів, який ігнорує пробіли. Це дозволяє розмістити регулярний вираз на кілька рядків і додавати коментарі.
Натан Фелман

9
Так само Python має re.Xака re.VERBOSE.
Крейг МакКуїн

2
Аналогічно xмодифікатор в tcl. Я вважаю, що це цілком стандартно, оскільки tcl, на відміну від інших мов, не використовує PCRE.
slebetman

2
@AndrewC Це одна з найсуворіших помилок, яку ця публікація могла отримати.
Джаспер Беккерс

28

Оскільки їм не вистачає найпопулярнішого інструмента для навчання у загальноприйнятих IDE: Майстра Regex немає. Навіть автозавершення. Ви повинні кодувати все це самостійно.


3
Тоді ви використовуєте неправильний IDE ... Навіть мій текстовий редактор надає підказки для регулярних виразів.
CurtainDog

1
Зі сторони, Expresso і The Regex Coach - дуже корисні інструменти для побудови регулярних виразів.
Мюн

22
Як у світі ви б автоматично заповнили регулярний вираз?
AmbroseChapel

3
EditPad Pro має підсвічування синтаксису для регулярних виразів у вікні пошуку, але я вважаю це більше дратівливим, ніж корисним, і тримати його вимкнено. Але я дуже вдячний, що повідомляє мені, коли у мене є неперевершені дужки; Зокрема, дужки можуть бути ведмедями, які слідкувати за ними.
Алан Мур

2
@AmbroseChapel - я запізнююся на пару років на цю дискусію. Але я створив механізм автодоповнення на regexhero.net/tester. Він ініційований загальними конструкціями всередині круглих (), квадратних []або фігурних {}дужок. Це також працюватиме відхилення від нахилу.
Стів Вортем


16

Я не думаю, що вони такі суперечливі.

Я також думаю, що ти наче відповів на власне запитання, бо ти вказуєш, як нерозумно було б користуватися ними скрізь ( Не все є звичайною мовою 2 ) або взагалі уникати їх використання. Ви, програміст, повинні прийняти розумне рішення про те, коли регулярні вирази допоможуть коду або зашкодять йому. Якщо ви зіткнулися з таким рішенням, дві важливі речі, які слід пам’ятати, - це ремонтопридатність (що передбачає читабельність) та розширюваність.

Щодо тих, хто їм особливо проти, то я здогадуюсь, що вони ніколи не навчились правильно їх використовувати. Я думаю, що більшість людей, які проводять лише кілька годин на гідному навчальному посібнику, розберуться і стануть вільними. Ось моя пропозиція щодо того, з чого почати:

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

Хоча на цій сторінці йдеться про регулярні вирази в контексті Python, я знайшов, що інформація дуже застосовна в інших місцях. Є кілька речей, які стосуються Python, але я вважаю, що вони чітко відзначаються та легко запам'ятовуються.


2
Здається, що сторінка перейшла на docs.python.org/howto/regex
Домінік К

@DMan Дякую Я відредагую свою відповідь, щоб відобразити.
allyourcode

11

Регулярні вирази - це рядки, якими є арифметичні оператори для чисел, і я не вважаю їх суперечливими. Я думаю, що навіть досить войовничий активіст ОО, як я (який, як правило, обирає інші об'єкти за рядками), буде важко відкинути їх.


7

Проблема полягає в тому, що реджекси потенційно настільки потужні, що ви можете робити з ними речі, для яких слід використовувати щось інше.

Хороший програміст повинен знати, де їх використовувати, а де ні. Типовим прикладом є аналіз нестандартних мов (див. Визначення правильності мови ).

Я думаю, що ви не можете помилитися, якщо спочатку обмежите себе реальними регулярними виразами (без розширень). Деякі розширення можуть трохи полегшити ваше життя, але якщо ви знайдете щось важке для вираження як справжній вираз, це може бути свідченням того, що регулярний вираз не є правильним інструментом.


5

Ви майже також можете запитати про те, чому гото є суперечливим.

В основному, коли ви отримуєте стільки "очевидних" повноважень, люди схильні зловживати ними у ситуаціях, для яких це не найкращий варіант. Наприклад, кількість людей, які просять проаналізувати CSV-файли або XML чи HTML в регексах, вражає мене. Це неправильний інструмент для роботи. Але деякі користувачі наполягають на тому, щоб використовувати реджекси так чи інакше.

Особисто я намагаюся знайти те щасливе середовище - використовуйте регекси для того, що їм добре, і уникаю їх, коли вони менш оптимальні.

Зауважте, що регулярні вирази все ще можна використовувати для розбору CSV, XML, HTML тощо. Але зазвичай це не в одному регулярному виразі.


Впевнений, що ти можеш розібрати будь-який із цих форматів в одному регулярному виразі, це сила регулярних виразів, дитино! Хочете ви цього робити чи ні, цілком інша справа.
Джаспер

4

Я не думаю, що "спірне" це правильне слово.

Але я бачив безліч прикладів, коли люди кажуть: "який регулярний вираз мені потрібно робити для такої і такої строкової маніпуляції?" які є проблемами XY.

Іншими словами, вони почали з припущення, що регулярний вираз - це те, що їм потрібно, але їм було б краще розділити (), переклад на зразок per // tr ///, де символи заміщені один на інший, або просто індекс ().


4

Це цікава тема.
Багато прихильників регулярних викидів, як видається, плутають стислість формули з ефективністю.
На додаток до цього, регулярний вираз, який вимагає багато думок, приносить його автору величезне задоволення, яке робить його легітимним відразу.

Але ... регекспи це так зручно , коли продуктивність не є проблемою , і вам потрібно швидко впоратися з виведенням тексту в Perl, наприклад. Крім того, хоча продуктивність є проблемою, можна вважати за краще не намагатися обіграти бібліотеку regexp, використовуючи домашній алгоритм, який може бути помилковим або менш ефективним.

Крім того, існує ряд причин, за які, наприклад, несправедливі критики

  • regexp не ефективний, оскільки побудова верхнього не очевидна
  • деякі програмісти «забувають» компілювати лише один раз регулярний вираз, який буде використано багато разів (наприклад, статичний зразок на Java)
  • деякі програмісти ідуть на пробну та помилкову стратегію - працює ще менше з регулярними виразками!

4

Що я думаю, що навчання Regex та підтримання регулярного вираження робить непопулярним, більшість розробників ледачі або більшість з них покладаються на зовнішні бібліотеки, щоб зробити для них розбір ... вони розраховують на Google для відповіді і навіть запитують на форумах про повний код їх проблеми. Але коли йдеться про реалізацію або зміну / підтримку регулярного виразка, вони просто не вдається.

Існує популярна приказка "Друзі не дозволяють друзям використовувати Regex для розбору HTML"

Але що стосується мене, я зробив повноцінні парсери HTML за допомогою Regex, і я вважаю, що regex краще розбирати HTML-рядки, як швидкі, так і пам'яті (якщо у вас є ідея, чого вам досягти :))


2
Я думаю, що нечесно списати більшість розробників ... як ледачий. Я б сказав, що синтаксис дуже криптичний, неінтуїтивно зрозумілий та сповнений ґаздів до неініційованих, що призводить до високого бар'єру для входу. З тієї ж причини Perl у багатьох "погана" репутація, але також є дуже потужною мовою. Це як намагатися читати математичні вирази, перш ніж пізнати символи. Це непросто, і розробники повинні бути судовими зі своїм часом, щоб знати, що вони отримають переваги для вивчення цього синтаксису.
Катастичне подорож

ти будете пропустити крайні випадки в HTML , так як HTML не є регулярним мовою. Ви впевнені, якщо маєте намір проаналізувати відомий підмножина HTML
Boyang

2

Регулярні вислови - серйозна таємниця для багатьох людей, включаючи і мене. Це чудово працює, але це як би дивитись на математичне рівняння. Я радий повідомити, хоча хтось нарешті створив зведене розташування різних функцій регулярного вираження на http://regexlib.com/ . Тепер, якщо Microsoft створить лише звичайний клас вираження, який автоматично виконує більшу частину загальних речей, як-от усунення букв або фільтрування дат.


2
Ви пропускаєте суть. Ідея регулярних виразів полягає в тому, що ви вкладаєте певний час у їх вивчення, і коли ви закінчите, вам більше не потрібен магічний клас "прочитати побачення". Натомість для них потрібно дуже мало зусиль. Більше того, для написання "для" yyyy / mm / dd "знадобиться так само мало зусиль, як і для написання" mm-dd-yyyy ", або навіть для" mm-yyyy / dd "(який виграв) "трапляється часто, але це приклад того, як ти можеш робити речі, які чарівний клас ніколи не може").
Джаспер,

1

Я вважаю регулярні вирази неоціненими часом. Коли мені потрібно зробити кілька «нечітких» пошуків, а можливо, замінить. Коли дані можуть змінюватися і мати певну випадковість. Однак, коли мені потрібно простий пошук і заміна, або перевірка на рядок, я не використовую регулярні вирази. Хоча я знаю багатьох людей, які це роблять, вони використовують це для всього. Це суперечка.

Якщо ви хочете вкласти стінку в стіну, не використовуйте молоток. Так, це спрацює, але до моменту, коли ви отримаєте молоток, я міг би поставити 20 стійок у стіну.

Регулярні вирази повинні використовуватися для того, для чого вони були розроблені, і не менше.


0

Хоча я вважаю, що регулярні вирази - це найважливіший інструмент, але найприємніше у них - це те, що існують різні реалізації. Незначні відмінності в синтаксисі, модифікаторах та "особливо жадібності" можуть зробити речі справді хаотичними, вимагаючи спроб та помилок, а іноді й генеруючи неприємні помилки.


чим реалізація регексу відрізняється своїм підходом до максимальної відповідності, що, на мою думку, ви називаєте «жадібністю»? Ви маєте на увазі різницю між лівою крайньою лівою та найдовшою лівою семантикою? Це єдина різниця, яку я знаю; тобто, жадібність козирять жадібністю чи навпаки .
tchrist

0

У деяких випадках я думаю, що ВИ ХОТИ ними користуватися. Наприклад, створити лексеру.

На мою думку, це точка зору на людей, які вміють писати реггекс, і людей, які не (або майже не знають). Я особисто кажу, що це добре подумати, наприклад, щоб підтвердити введення форми, будь то в JavaScript для попередження користувача або на серверній мові.


0

Я думаю, що це менш відома методика серед програмістів. Отже, широкого прийняття для цього немає. І якщо у вас є нетехнічний менеджер для перегляду вашого коду чи перегляду вашої роботи, то регулярний вираз дуже поганий. Ви витратите години на написання ідеального регулярного виразу, і отримаєте кілька відміток для модуля, думаючи, що він / вона написала так мало рядків коду. Крім того, як сказано в іншому місці, читання регулярних виразів є дуже складним завданням.


1
Читання регулярних виразів є складним завданням лише тоді, коли програміст, який їх створив, не зміг використати пробіл, коментарі, буквено-цифрові ідентифікатори та, можливо, також вбудовані підпрограми через затримку виконання. Коротше кажучи, всі методи інженерії програмного забезпечення, застосовні до загального програмування, також повинні дотримуватися у регулярних виразах. Якщо ці принципи ігнорувати, письменник не виробляє професійний код.
tchrist

Я думаю, що ваш менеджер не знає, що "Справжній герой програмування - це той, хто пише негативний код".
Радєєв

Якщо ваш менеджер збирається заграти вас за виконання роботи за допомогою 3-х рядків коду (включаючи регулярні вирази), похваливши якогось колега-дуфа, який зробив це в 900 рядках Assembler ... Я пропоную знайти нову роботу.
Філ Перрі

0

Гідні системи регулярного вираження, такі як використовувані в lex та yacc для визначення компілятора, є хорошими, дуже корисними та чистими. У цих системах типи виразів визначаються з точки зору інших. Це "суперечливі" (сміття) жахливі неправильно сформовані непрочитані лінійно-шумові гігантські однолінійні регулярні вирази, які зазвичай зустрічаються у коді perl та sed (тощо).


-4

Найкраще правильне та звичайне використання для регулярного виразу - це перевірка формату адреси електронної пошти.

Це гарне застосування.

Я безліч разів використовував регулярні вирази як одноразові в TextPad для масажу плоских файлів, створення файлів csv, створення операторів вставки SQL і подібного.

Добре написані регулярні вирази не повинні бути надто повільними. Зазвичай такі варіанти, як тонна дзвінків на Замінити, є набагато повільнішими варіантами. Можна також зробити це за один прохід.

Багато ситуацій вимагають точно регулярних виразів і нічого іншого.

Заміна спеціальних символів, що не друкуються, на невинних символів - ще одне корисне використання.

Звичайно, я можу собі уявити, що є деякі кодові бази, які надмірно використовують регулярні вирази на шкоду ремонтопридатності. Я цього ніколи не бачив. Мене фактично ухилили рецензенти за те, що вони недостатньо використовували регулярні вирази.


10
Досвід показує, що режекси - насправді досить поганий інструмент для перевірки формату адрес електронної пошти. По-справжньому повноцінний валідатор формату, реалізований як регулярний вираз, - це багатосотні символи чудовисько, тоді як більшість коротших валідаторів «достатньо хороших», на які у більшості людей знадобиться 5 хвилин, будуть відхиляти великі категорії дійсних, доступних адрес.
Дейв Шерохман

Я чую, чувак. Я говорив про "достатньо хороших", і хоча теоретично великі качки можуть бути великими, врахуйте відсоток покриття, який ви отримуєте за такий короткий вираз. Я теж бачив жахливість, але яка ваша елегантна альтернатива?
Кріс Морлі

2
Я використовував щось на кшталт \ w @ \ w +. \ W +, щоб швидко знайти адресу електронної пошти у величезному каталозі файлів, де важлива швидкість і кілька помилкових позитивів чи помилкових негативів не мали значення. Але найкращим способом перевірити адресу електронної пошти, здається, є надсилання електронної пошти на неї.
RossFabricant

Так, електронна адреса специфікація неприємний безлад stackoverflow.com/questions/611775/…
Нік Ван Брунт

@ Nick, @Dave: Перевірка поштової адреси не повинна бути неприємним безладом.
tchrist
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.