RegExp [АйТи бубон]

  1. Максималізм квантіфікатора *
  2. Мінімальні квантіфікатори *?
  3. Завершувач рядків Unicode
  4. Випереджаючі, ретроспективні перевірки
  5. Unicode. Алфавіти і блоки: \ р, \ Р
  6. Розбити число на розряди

Регулярні вирази (regular expressions, скор. RegExp, RegEx) - це формальна мова пошуку і здійснення маніпуляцій з підрядками в тексті, заснований на використанні метасимволов (wildcard characters). По суті це рядок-шаблон (pattern), що складається з символів і метасимволов і задає правило пошуку.

При реалізації механізмів регулярних виразів зазвичай використовуються дві базові технології: НКА (недетермінований кінцевий автомат) і ДКА (детермінований кінцевий автомат). Механізми відрізняються підходом до порівняння регулярного виразів з рядком. Кажуть, що механізм НКА «управляється регулярним виразом», а механізм ДКА «управляється текстом». Найпоширенішим є НКА.

  • Програми використовують НКА: Perl, PHP , бібліотека PCRE , .NET, Python, JavaScript .
  • Програми використовують ДКА: AWK приклади використання , Flex, lex, MySQL . Немає мінімальних квантіфікаторов. ДКА прагне до максимального захоплення.

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

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

Одне і теж регулярний вираз найчастіше в різному тексті буде вести себе по різному, так як врахувати всі нюанси різного контенту дуже важко

Таблиця метасимволов Елементи позначають окремий символ Метасимвол Назва Інтерпретація. Точка Один будь-який символ (в деяких реалізаціях виключаючи символ нового рядка). Вираз ac відповідає рядкам "abc", "a1c" і "ac". [...] Символьний клас Будь-який з перелічених символів. Використовуючи тире можна вказати діапазон символів, наприклад, [af] - те ж саме, що [abcdef] [^ ...] Інвертований символьний клас Будь-який символ, що не міститься у класі. \ Символ Екранування Якщо перед метасимволом ставиться екранує префікс \, то символ інтерпретується як відповідний літерал. Наприклад, символ "." є спецсимволи, якщо ж потрібно щоб він сприймався буквально, тобто означав саме точку, то потрібно записати так: "\." Квантіфікатори? Знак питання мінімальні квантіфікатори . Допускається один екземпляр (жоден з них не потрібно). Повторення попереднього елемента нуль або один раз. Еквівалентно {0,1} * Зірочка жадібний квантіфікатор . Допускається будь-яку кількість екземплярів (жоден з них не потрібно). Повторення попереднього елемента (включаючи цифри, букви або виразу) нуль або більше разів. Еквівалентно {0,} Наприклад: [0-9] * означає будь-яку кількість цифр від 0 до 9. Вираз. * Означає будь-яку кількість будь-яких символів. + Плюс Потрібно один екземпляр, допускається будь-яку кількість екземплярів. Повторення попереднього елемента один або більше разів. Еквівалентно {1,} {min, max} Інтервальний квантіфікатор, Фігурні дужки Потрібно min примірників, допускається max примірників. Варіанти запису: {n} повторення попереднього елемента n раз (n - натуральне число). {N,} повторення попереднього елемента n або більше разів. {N, m} повторення попереднього елемента від n до m раз. Фігурні дужки крім випадку інтервального квантіфікатора - є звичайними літералами. Позиційні метасимволу ^ Кришка, будиночок, циркумфлекс Позиція на початку рядка. Якщо встановлений прапор багаторядкового пошуку, то початок будь-якого рядка в тексті. \ A Позиція на початку рядка. Метасимвол  \ A (якщо він підтримується) збігається тільки на початку тексту незалежно від режиму пошуку. $ Знак долара Позиція в кінці рядка. Якщо встановлений прапор багаторядкового пошуку, то кінець будь-якого рядка в тексті. \ Z \ z Позиція в кінці рядка. Метасимвол  \ Z (якщо він підтримується) зазвичай відповідає метасимвол  $  в стандартному режимі, що часто означає збіг у кінці тексту або перед символом нового рядка, завершальним текст. Парний метасимвол  \ z збігається тільки в кінці рядка без урахування можливих символів нового рядка. \ <Або \ b Кордон слова Позиція на початку слова. \ B межа слова, т. Е. Позиція між словом і пропуском або переведенням рядка. /> Або \ b Кордон слова Позиція в кінці слова. \ B межа слова, т. Е. Позиція між словом і пропуском або переведенням рядка. \ b Забой Зазвичай відповідає ASCII символу <BS>, код 010 (в вісімковій системі). Зверніть увагу: у багатьох діалектах  \ b інтерпретується як символ забою тільки всередині символьних класів, а за їх межами - як межа слова. У багатьох реалізація \ b тільки для латинських слів і Unicode не розуміє. \ B Кордон слова Будь-яка позиція крім кордону слова. Інші метасимволу | Конструкція вибору Будь-яке з перерахованих виразів. Наприклад, умова "або" (a або b). Так як в даному випадку по обидва боки роздільник рівно по одному символу, то можна замінити на [ab] (...) Круглі дужки Служить для обмеження конструкції вибору, групування для застосування квантіфікаторов і «збереження» тексту для зворотних посилань. Подвираженія нумеруються відповідно до номером один по одному відкриває круглої дужки, починаючи з 1. подвираженія можуть бути вкладеними - наприклад,  (Washington (• DC)?) . Звичайні (зберігають) круглі дужки  (...)  можуть бути застосовані тільки з метою угруповання, а й в цьому випадку відповідна спеціальна змінна заповнюється текстом збіги. (?: ...) Круглі дужки Служить для угруповання символів без збереження. Тобто не можна використовувати зворотні посилання для вираження в таких дужках. \ 1, \ 2, ... Зворотній посилання Текст, раніше співпав з першої, другої і т.д. парами круглих дужок. Метасимволи для подання машіннозавісімих керуючих символів \ a Сигнал Сигнал (при «виведенні» лунає звуковий сигнал). Зазвичай відповідає ASCII символу <BEL>, код 007 (в вісімковій системі). \ e Символ Escape Зазвичай відповідає ASCII символу <ESC>, код 033 (в вісімковій системі). \ f Переклад формату Зазвичай відповідає ASCII символу <FF>, код 014 (в вісімковій системі). \ n Символ перекладу рядка Новий рядок. На більшості платформ (включаючи Unix і DOS / Windows) зазвичай відповідає ASCII символу <LF>, код 012 (в вісімковій системі). В системі MacOS зазвичай відповідає ASCII символу <CR>, код 015 (в вісімковій системі). У Java і мовами .NET завжди відповідає ASCII символу <LF> незалежно від платформи. \ r Символ повернення каретки Зазвичай відповідає ASCII символу <CR>. В системі MacOS зазвичай відповідає ASCII символу <LF>. У Java і мовами .NET завжди відповідає ASCII символу <CR> незалежно від платформи. \ t Символ горизонтальної табуляції Горизонтальна табуляція. Зазвичай відповідає ASCII символу <НТ>, код 011 (в вісімковій системі). \ v Символ вертикальної табуляції Вертикальна табуляція. Зазвичай відповідає ASCII символу <VT>, код 013 (в вісімковій системі). Інші метасимволу 2 \ s відповідає будь-якому «Пробільні» символу (пробіл, табуляція, новий рядок, переклад формату і т. Д.). \ S Будь-який символ, крім пробільних. Все, що не відноситься до  \ s \ w Цифра, літера (латинський алфавіт) або знак підкреслення. Еквівалентно [0-9a-zA-Z_]. Часта конструкція для пошуку слів \ w + \ W Будь-який символ, крім цифр, букв (латинський алфавіт) і знака підкреслення. Все, що не відноситься до \ w. Еквівалентно [^ 0-9a-zA-Z_] \ d Цифра. Еквівалентно [0-9] \ D Будь-який символ, крім цифр. Все, що не відноситься до \ d Еквівалентно [^ 0-9]

Максималізм квантіфікатора *

Регулярний вираз . *  завжди поширює збіг до кінця рядка. Це пов'язано з тим, що . *  прагне захопити все, що може. Втім, пізніше частина захопленого може бути повернута, якщо це необхідно для загального збіги. Іноді це поведінка викликає чимало проблем. Розглянемо регулярний вираз для пошуку тексту, укладеного в лапки. На перший погляд напрошується просте  ". *" , але спробуйте на підставі того, що нам відомо про . * , припустити, який збіг буде знайдено в рядку:

The name "McDonald's" is said "makudonarudo" in Japanese

Після збігу першого символу "управління передається конструкції . * , яка негайно захоплює все символи до кінця рядка. Вона починає знехотя відступати (під натиском механізму регулярних виразів), але тільки до тих пір, поки не буде знайдено збіг для останньої лапки. Якщо прокрутити відбувається в голові, ви зрозумієте, що знайдене збіг буде виглядати так (виділено нижнім підкресленням):

The name "McDonald's" is said "makudonarudo" in Japanese

Знайдений зовсім не той текст, який ми шукали. Це одна з причин, за якими не варто зловживати . * , - якщо не враховувати проблем максимального збігу, ця конструкція часто призводить до несподіваних результатів. Як же обмежити збіг рядком "McDonald's"? Головне - зрозуміти, що між лапками має знаходитися не «все, що завгодно», а «все, що завгодно, крім лапок». Якщо замість . *  скористатися виразом  [^ "] * , збіг не пройде далі закриває лапки.

При пошуку збігу для  "[^"] * " механізм поводиться практично так само. Після збігу першої лапки  [^"] *  прагне захопити якомога більшу потенційне збіг. В даному випадку це збіг поширюється до лапки, наступного після McDonald's. На цьому місці пошук припиняється, оскільки  [^ "]  не збігається з лапками, після чого управління передається закриває лапки в регулярному виразі. Вона благополучно збігається, забезпечуючи загальне збіг:

The name "McDonald's" is said "makudonarudo" in Japanese

Насправді в цьому прикладі можливий несподіваний поворот, пов'язаний з тим, що в більшості діалектів  [^ "]  може збігатися з символом нового рядка, a . - не може. Якщо ви хочете запобігти можливому вихід за кордон логічної рядка, використовуйте вираз  [^ "\ n] .

Мінімальні квантіфікатори *?

У деяких варіантах НКА підтримуються мінімальні квантіфікатори, при цьому *? є мінімальним аналогом квантіфікатора *. Квантіфікатор прагне до мінімального захоплення.

Завершувач рядків Unicode

В Unicode визначається декілька разів (а також одна послідовність з двох символів), які вважаються завершувач рядків (line terminators).

Завершувач рядків в Юникоде Символ Опис LF U + 000A Переклад рядка ( ASCII ) VT U + 000B Вертикальна табуляція (ASCII) FF U + 000C Переклад формату (ASCII) CR U + 000D Повернення каретки (ASCII) CR / LF U + 000D U + 000A Повернення каретки / переведення рядка (ASCII послідовність) NEL Наступний рядок ( Юнікод) LS U + 2028 Роздільник рядків (Юнікод) PS U + 2029 Роздільник абзаців (Юнікод)

При наявності повноцінної підтримки з боку програми завершувач рядків впливають на результати читання рядків з файлу (в сценарних мовах - включаючи файл, з якого читається програма). У регулярних виразах вони можуть впливати як на те, які символи збігаються з ., так і на можливість збігу метасимволов  ^ ,  $  і  \ Z

Випереджаючі, ретроспективні перевірки

  • Випереджальна перевірка (? = ...), (?! ...) - аналізує текст, розташований праворуч і перевіряє можливість збігу вираження.

  • Ретроспективна перевірка (? ⇐ ...), (? <! ...) - текст аналізується до лівого краю.

Приклади використання:

Unicode. Алфавіти і блоки: \ р, \ Р

властивості Unicode , Алфавіти і блоки: \ р {властивість}, \ Р {властивість}. На концептуальному рівні Юнікод є відображення безлічі символів на безліч кодів, але стандарт Юникода не зводиться до простого перерахування пар. Він також визначає атрибути символів (наприклад, «цей символ є рядкової буквою», «цей символ пишеться справа наліво», «цей символ є діакритичним знаком, який повинен об'єднуватися з іншим символом» і т. Д.). Рівень підтримки цих атрибутів залежить від конкретної програми, але багато програм з підтримкою Юнікоду дозволяють знаходити хоча б деякі з них за допомогою конструкцій  \ p {атрибут}  (символ, що володіє зазначеним атрибутом) і  \ P {атрибут}  (символ, що не володіє атрибутом).

Рекомендації по оптимізації регулярних виразів.

  • Прискорене досягнення збіги. Керуючись знаннями принципів роботи традиційного механізму НКА, можна привести механізм до збігу з прискореного шляху. Розглянемо приклад  this | that. Кожна альтернатива починається з th, якщо у першій альтернативи не знайдеться збіг для th, то th другий альтернативи теж свідомо не співпаде, тому така спроба свідомо завершиться невдачею. Щоб часом не витрачалося даром, можна сформулювати той же вислів у вигляді th (?: Is | at) . В цьому випадку th перевіряється всього один раз, а щодо витратна конструкція вибору відкладається до моменту, коли вона стає дійсно необхідною. Крім того, в вираженні th (?: Is | at)  проявляється початковий літерал th, що дозволяє задіяти ряд інших оптимізацій.

  • Прив'язка до початку тексту / логічної рядка. Цей різновид оптимізації розуміє, що регулярні вирази, що починаються з  ^ , можуть збігтися тільки від початку рядка, тому їх не слід застосовувати з інших позицій.

  • Прив'язка до кінця тексту / логічної рядка. Цей різновид оптимізації заснована на тому, що збіги деяких регулярних виразів, які завершуються метасимволом  $  або іншими якорями кінця рядка, повинні відділятися від кінця рядка певною кількістю байтів. Наприклад, для вираження regex (es)? $  збіг має починатися не більше ніж за вісім символів від кінця рядка, тому механізм може відразу перейти до цієї позиції. При великій довжині цільового тексту це істотно скорочує кількість початкових позицій пошуку. Вісім, а не сім, тому що в багатьох діалектах  $  може збігатися перед завершальним символом нового рядка.

  • Виняток по першому символу / класу / підрядку. Даний вид оптимізації керується інформацією (будь-який збіг має починатися з конкретного символу або підрядка), на підставі якої проводиться швидка перевірка і застосування регулярного виразу лише на зазначені позицій рядка. Наприклад, вираз this | that | other може збігатися тільки в позиціях, що починаються з  [ot] ; механізм перевіряє всі символи рядка і застосовує вираження лише на зазначені позицій, що може привести до величезної економії часу. Чим довше перевіряється рядок, тим менше ймовірність помилкової ідентифікації початкових позицій.

  • Використовуйте несохраняющейся круглі дужки. Якщо ви не використовуєте текст, що співпадає з подвираженія в круглих дужках, використовуйте несохраняющейся дужки  (?: ...) . Крім прямого виграшу через відсутність витрат на збереження з'являється побічна економія - стану, що використовуються при поверненні, стають менш складними і тому швидше відновлюються.

Розбити число на розряди

Завдання: Розбити число на розряди наприклад запитом. Формально задача виглядає так «вставити коми у всіх позиціях, у яких кількість цифр праворуч кратно трьом, а зліва є хоча б одна цифра»

Друга вимога виконується за допомогою ретроспективної перевірки. Однією цифри зліва досить для виконання цієї вимоги, а цей критерій задається виразом  (? ⇐ \ d) .

Група з трьох цифр визначається виразом  \ d \ d \ d. Укладемо її в конструкцію  (...) + , щоб збіг могло складатися з декількох груп, і завершимо метасимволом  $ , щоб гарантувати відсутність символів після збігу. Само по собі вираз  (\ d \ d \ d) + $  збігається з групами з трьох цифр, наступними до кінця рядка, але в конструкції випереджаючої перевірки  (? = ...)  воно збігається з позицією, праворуч від якої до кінця рядки слідують групи з трьох цифр. Однак перед першою цифрою кома не ставиться, тому збіг додатково обмежується ретроспективної перевіркою  (? ⇐ \ d) .

Щоб вираз стало більш ефективним можна додати несохраняющейся дужки?: В (?: \ D \ d \ d), в цьому випадку підсистема регулярних виразів не витрачатиме ресурси на збереження тексту в круглих дужках.

  • Реалізація PHP ( PCRE ): <? Php $ n = "7500400300222"; // $ n = preg_replace ( '/ (? <= \ D) (? = (\ D \ d \ d) + $) /', ',', $ n); $ N = preg_replace ( '/ (? <= \ D) (? = (?: \ D \ d \ d) + $) /', ',', $ n); echo "$ n \ n"; ?>

regexp.txt · Останні зміни: 2018/08/18 2:03 (зовнішня зміна)

Квантіфікатори?
1. подвираженія можуть бути вкладеними - наприклад,  (Washington (• DC)?
Як же обмежити збіг рядком "McDonald's"?
Мінімальні квантіфікатори *?
У деяких варіантах НКА підтримуються мінімальні квантіфікатори, при цьому *?
Наприклад, для вираження regex (es)?
Щоб вираз стало більш ефективним можна додати несохраняющейся дужки?