Короткий довідник щодо синтаксису формальних виразів

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

Класи символів

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

Приклади:

Представлення Клас
[a-z] Літери нижнього регістру. Без символів із акцентами та лігатур.
[a-z0-9] Літери нижнього регістру від a до z або цифри від 0 до 9.
[A-Za-z-] Літери верхнього або нижнього регістру чи дефіс. Щоб включи дефіс до класу, вам слід розташувати його на початку або наприкінці класу, щоб рушій не сплутав його із дефісом, який визначає діапазон символів.
[^0-9] Будь-який символ, окрім цифри. Символ каре (^), розташований на початку класу, виключає символи з класу (формує доповнення до класу).
[[a-z]--[aeiouy]] Приголосні нижнього регістру. Клас можна включати до іншого класу. Символи -- виключають клас, який слідує за ними.
[\w--[\d_]] Усі літери (разом із літерами із акцентами і літерами будь-яких абеток). Скорочення класів можна використовувати всередині класу.

Приклад:

<[^<>]+> to select an HTML tag

Скорочення для класів символів

Представлення Клас
\d Цифра (те саме, що і [0-9])
\D Будь-який нечисловий символ (те саме, що і [^0-9])
\w Буквенно-цифровий символ ([a-zA-Z0-9]), включно із символами із акцентами та лігатурами.
\W Будь-який символ, який не є частиною слів.
\s Пробіл, нерозривний пробіл, табуляція або символ розриву рядка.
\S Будь-який символ, який не є пробілом
. Будь-який символ, окрім символу розриву рядка. Скористайтеся пунктом «крапка — усі» або модифікатором формального виразу (?s), щоб включити до класу символ розриву рядка.

Лічильники

Лічильник Кількість входжень підвиразу, який передує лічильнику, до виразу
? 0 або 1 входження до виразу. Те саме, що {0,1}
+ 1 або більше входжень підвиразу. Те саме, що {1,}
* 0, 1 або більше входжень підвиразу. Те саме, що {0,}
{n} Точно n входжень підвиразу
{min,max} Кількість входжень між мінімальним і максимальним значенням.
{min,} Кількість входжень, що перевищує мінімальне значення або дорівнює йому.
{,max} Кількість входжень між 0 і максимальним значенням, включно.

Жадібність

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

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

Альтернативи

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

Виключення

Метод 1

взірець_для_виключення(*SKIP)(*FAIL)|взірець_для_відповідності

Приклад:

"Blabla"(*SKIP)(*FAIL)|Blabla

встановлює відповідність за виразом Blabla, у рядку Blabla або «Blabla or Blabla», але не у рядку «Blabla».

Метод 2

взірець_для_виключення\K|(взірець_для_відповідності)

"Blabla"\K|(Blabla)

встановлює відповідність за виразом Blabla, у рядку Blabla або «Blabla or Blabla», але не у рядку «Blabla».

Прив’язки

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

\b
Позначає межу слова, тобто перехід від пробільних до непробільних символів, і навпаки. Наприклад, ви можете скористатися виразом \bsurd, щоб знайти the surd, але при цьому пропустити слово absurd.
^
Відповідає початку рядка (у багаторядковому режимі, який є типовим).
$
Відповідає кінцю рядка (у багаторядковому режимі, який є типовим).
\K
Скидає початок відповідника до його початку у взірці. У деяких рушіях обробки формальних виразів (але не у calibre) заборонений перегляд назад на змінну довжину, особливо, якщо використано лічильник. Ви можете скористатися \K для таких рушіїв. Це також дозволить обійти обмеження написанням еквівалентного додатного перегляду назад змінної довжини.

Групи

(вираз)
Захоплена група, яка зберігає рядок-відповідник і яку можна згодом використовувати у взірцях пошуку або заміни за допомогою виразу \n, де n є номером групи (нумерація починається з 1 у напрямку читання).
(?:вираз)
Група, яка не містить відповідник.
(?>вираз)
Атомарна група: якщо буде встановлено відповідність виразу, рушій обробки формальних виразів продовжить обробку решти взірця. Якщо під час цієї обробки загальну відповідність встановити не вдасться, рушій не повертатиметься до атомарної групи, щоб спробувати інші комбінації з виразом. Атомарні групи не можна захоплювати.
(?|вираз)
Розгалуження групи: гілки альтернативних варіантів буде включено до виразу із однаковими номерами груп.
(?<назва>вираз)
Група з назвою «назва». Відповідник групи далі можна використати у взірці пошуку так: (?P=назва), у заміні так: \g<назва>. Дві різні групи можуть використовувати одну назву.

Перегляди вперед і назад

Перегляд Значення
?= Додатний перегляд вперед (слід розташовувати після відповідника)
?! Від’ємний перегляд назад (слід розташовувати після відповідника)
?<= Додатний перегляд назад (слід розташовувати перед відповідником)
?<! Від’ємний перегляд назад (слід розташовувати перед відповідником)

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

Якщо відбувається пошук декількох відповідників у тексті, на початковій позиції кожної спроби встановлення відповідності, перегляд назад може виконувати вивчення символів до поточної позиції. Тому у рядку 123 взірець (?<=\d)\d (цифра перед цифрою) має, теоретично, відповідати підрядкам 2 і 3. З іншого боку, взірець \d\K\d відповідає лише підрядку 2, оскільки початкова позиція після першого відповідника розташована безпосередньо перед підрядком 3, а там недостатньо символів для встановлення відповідності другого підрядка. Так само, \d(\d) захоплює лише 2. Практично, у рушії обробки формальних виразів calibre, позитивний пошук назад працює так само, і встановлює відповідність лише підрядка 2, на відміну від теорії.

Групи можна розташовувати у переглядах, але захоплення у таких випадках буде корисним доволі нечасто. Як би там не було, якщо виникне потреба у ньому, слід бути дуже обережним у використанні лічильників у переглядах назад: «жадібність», пов’язана із тим, що немає зворотного стеження, може призвести до несподіваних результатів захоплення. З цієї причини варто користуватися \K замість додатного перегляду назад, якщо у вас є лічильник (або, ще гірше, декілька) у групі захоплення додатного перегляду назад.

Приклад від’ємного перегляду вперед:

(?![^<>{}]*[>}])

Якщо розташувати цей вираз наприкінці взірця, він запобігатиме встановленню відповідності усередині теґу або стилю, вбудованого до файла.

Якщо це можливо, завжди варто «прив’язувати» перегляди, щоб зменшити кількість кроків, які потрібні для досягнення результату.

Рекурсія

Представлення Значення
(?R) Рекурсія за цілим взірцем
(?1) Рекурсія єдиного взірця нумерованої групи, у нашому прикладі, групи 1.

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

start-pattern(?>atomic sub-pattern|(?R))*end-pattern

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

“((?>[^“”]+|(?R))*[^“”]+)”

Цим шаблоном можна також скористатися для внесення змін до пар теґів, які можна вбудовувати, зокрема теґів <div>.

Спеціальні символи

Представлення Символ
\t табуляція
\n розрив рядка
\x20 (розривний) пробіл
\xa0 нерозривний пробіл

Метасимволи

Метасимволи — це символи, які мають особливе значення для рушія обробки формальних виразів. Дванадцять із метасимволів має бути екрановано символом зворотної похилої риски (\), щоб вони втратили своє особливе значення і стали звичайними символами у взірці:

^ . [ ] $ ( ) * + ? | \

Сім інших метасимволів не потребують екранування символом зворотної похилої риски (втім, їх може бути екрановано без будь-яких наслідків):

{ } ! < > = :

Спеціальні символи втрачають свій статус, якщо їх використано у класі (між квадратними дужками, []). Кінцева дужка і дефіс мають особливий статус у межах визначення класу. Поза визначенням класу дефіс є звичайним дефісом, а кінцева квадратна дужка лишається метасимволом.

Символ похилої риски (/) і символ номера (або символ-хеш) (#) не є метасимволами. Потреби у їхньому екрануванні немає.

У деяких інструментах, зокрема regex101.com, де використовується рушій Python, подвійні лапки мають особливе значення як роздільник, тому їх слід екранувати або вдаватися до зміни параметрів роботи рушія. У редакторі calibre подвійні лапки не мають особливого значення.

Режими

(?s)
Робить так, що крапка (.) вважатиметься відповідником будь-якого символу, зокрема і символу розриву рядка.
(?m)
Робить прив’язки ^ і $ відповідниками початку і кінця рядків, а не відповідниками початку або кінця усього тексту.