Регулярні вирази: що це, як скласти, навіщо використовувати
Я не знаю людини зі сфери інтернет-маркетингу, яка в своїй роботі жодного разу не зустрічалася з регулярними виразами. (Ви знаєте? Тегніть її, будь ласка, в коментарях). Онлайн-маркетинг і базові знання про регулярки ходять поруч — без останніх дуже багато операцій доведеться виконувати вручну, замість того, щоб написати простий регулярний вираз вигляду ^[a-z].*-\/[0-9]\.html$|^[A-Z][0-9].*\.php$ й виконати завдання за декілька хвилин.Вас налякав вигляд вираження? Це нормальна перша реакція, якщо ви не в темі. Як і в усьому, тут треба розібратися, зрозуміти логіку і результат не змусить довго чекати — ви зможете оперативно працювати з текстами, url-адресами й іншими даними. А оскільки автоматизація — наше все, я пишу цю статті і сподіваюся, що вона допоможе самостійно складати прості регулярні вирази, які ви будете використовувати в задачах з оптимізації сайту або запуску контекстної реклами.
Що таке регулярні вирази?
Це формальна мова пошуку і маніпуляцій з підрядками в тексті. У ньому використовується рядок-зразок із символів і метасимволов, що задає правило пошуку.
Основи синтаксису
Перша група символів — це шукані букви або цифри, які позначають самі себе.
Друга група — це спецсимволи, які вказують деяку дію або впливають на інші частини регулярного виразу, повторюючи і/або змінюючи їх значення.
Задає один довільний символ | |
Замінює символ з квадратних дужок | |
Задає один символ, якого не повинно бути в дужках | |
Задає один символ, який не міститься в квадратних дужках | |
Позначає початок послідовності | |
Позначає закінчення рядка | |
Позначає довільне число повторень одного символу | |
Позначає строго одне повторення символу | |
Позначає один символ, який повторюється кілька разів | |
Логічне АБО. Або вираз до, або вираз після символу | |
Екранування. Для використання метасимволов як звичайних | |
Групує символи всередині | |
Вказується число повторень попереднього символу |
Регулярний вираз може складатися тільки з простих символів, наприклад «Привіт», або тільки з спецсимволов – ^\D.*. Але більш зрозумілим і ефективним варіантом є мікс обох груп символів – ^Привіт, \.*$.
Давайте розберемося з можливостями спецсимволів. Для зручності розіб’ємо їх на категорії:
- символьні класи — \d \w \s и .;
- символ екранування — \;
- якоря — ^ и $;
- квантіфікатори — * + ? и {n};
- оператор АБО — |;
- дужки — () [] и {};
- Символьні класи — \d \w \s и Для пошуку інформації достатньо скористатися рядком введення, ввести необхідний текст і натиснути кнопку «Знайти». Але іноді потрібно знайти номери телефонів, не одну адресу електронної пошти і тд. В цьому випадку простим введенням в рядок пошуку не обійтися.Тут на допомогу приходять символьні класи, що дозволяють «перетворити» ряд простих символів в коротку команду. Це дуже зручно, якщо стоїть завдання знайти рядки, які містять будь-яку цифру або тільки букви, або не порожні, які іноді теж потрібні.
Ось основні символьні класи:
- \d — відповідає одному символу, який є цифрою, еквівалент класу [0-9];
- \w — відповідає слову (може складатися з букв, цифр і підкреслення), еквівалент [a-zA-Z0-9_];
- \s — відповідає символу пробілу (включаючи табуляцію і переривання рядка), еквівалент [ \t\n\r\f\v];
- . — відповідає будь-якому символу;
- У операторів \d, \w и \s також є заперечення ― \D, \W и \S відповідно.
Наприклад, оператор \D буде шукати відповідні протилежні \d, тобто символи, які не є цифрами.
- Символ екранування — \Давайте звернемо увагу на символ зворотного слеша – \. Ми вже знаємо, що він використовується для позначення класів символів. Крім цього, зворотний слеш володіє ще однією важливою здатністю — він відключає дію інших спецсимволів, якщо нам потрібно передати їх значення буквально.Припустимо, ми хочемо знайти крапку. Не «будь-який символ», а саме крапку. Щоб використовувати спеціальний символ як звичайний, необхідно додати перед ним зворотну косу риску. Це називається«екранування символу».
- ЯкоряЧасто виникає необхідність знайти рядки, які починаються або закінчуються конкретним символом, словом або цифрою. Наприклад, щоб знайти URL-адреси, які починаються на start, досить ввести ^start у пошуковий рядок, а закінчуються на end — просто додати символ долара в кінці — end$. Дуже просто.^ (символ каретки) — представляє початок рядка;
$ (символ доллара) — представляє кінець рядка.
Ці дві позиції в рядку називаються якорями, оскільки вони дозволяють нам прив’язати шаблон регулярного виразу до конкретної крапки в рядку.
<p.До якорів ще можна віднести \A і \Z, що позначають початок і кінець тексту, відповідно.
- Квантіфікатори — * + ? и {n}Коли з’являється необхідність вказати кількість повторень якогось символу, наприклад, у разі перевірки номера телефону, номера банківської картки та в багатьох інших випадках, де присутнє повторення символів, у гру вступають квантіфікатори.Квантифікатори — це вказівка кількості повторень символів.
* (зірочка) — означає 0 або більшу кількість повторень.
+ (плюс) — означає одне або більшу кількість повторень. Щоб рядок відповідав регулярному виразу, має бути хоча б одне повторення зазначеного символу (в цьому відмінність від попереднього квантіфікатора).
? (знак питання) — означає 0 або одне повторення. Тобто або одне повторення, або жодного.
Коли виникає необхідність вказати конкретну кількість або інтервал повторень, його можна вказати всередині фігурних дужок, відразу ж після символу, який потрібно повторювати.Є 3 варіанти:
{n} — конкретна кількість — n-повторень.
{min,} – мінімальна кількість повторень і до нескінченності.
{min,max} — інтервал кількостей повторень.Ці символи значно скорочують регулярні вирази. Наприклад, при перевірці номера банківської картки. Ми знаємо, що такий номер складається рівно з 16 цифр. Тому в регулярному виразі нам потрібно вказати цю конкретну кількість цифр. А щоб не писати 16 раз поспіль символ класу ‘ \d ‘, ось так:
var reg = /^\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d$/;
Ми можемо скористатися квантіфікатором повторень і написати регулярний вираз таким чином:
var reg = /^\d{16}$/;
- Оператор АБО — |Щоб перевірити, чи задовольняє рядок хоча б один з шаблонів</ em>, можна скористатися оператором АБО, який записується за допомогою символу |.Так, під шаблон «Привіт|Здоровенькі були» потрапляють рядки «Привіт» або «Здоровенькі були» відповідно. Особливо зручно використовувати перерахування всередині дужкових груп. Так, наприклад (?:a|b|c|d) повністью еквівалентно [abcd] (у даному випадку другий варіант кращий через продуктивність і читання).
- Дужки — () [] и {}Регулярні вирази пропонують нам три види дужок:
- звичайні дужки — ();
- квадратні дужки — [];
- фігурні дужки — {}.
Звичайні круглі дужки. Головне, що потрібно про них знати, — вони дуже ефективно працюють з оператором АБО виконуючи функцію угруповання.
Візьмемо простий приклад, необхідно знайти рядок з похвалою «Молодець». Начебто все просто: пропишемо це слово цілком як шаблон і справ. Але насправді все не так — слово «Молодець» може зустрічатися інакше, наприклад, «Молодчага» (із закінченням -чага замість -ець). Чим не похвала? Відповідно, в регулярному виразі необхідно вказати альтернативу — ець|чага.
Спробуємо:
Молодець|чага
Такий запит знайде нам «Молодець» або «чага»
Трохи не те. Вся річ у тому, що символ альтернативи | бере в якості варіантів все, що знаходиться ліворуч і праворуч від нього. Як же нам вказати, що необхідно узяти тільки по одній букві праворуч і ліворуч? Ось тут на допомогу приходять круглі дужки, які виконають необхідне угрупування.
Молод(ець|чага)
Ось тепер все добре. Крім того цей вид дужок дозволяє запам’ятовувати знайдене. Оскільки таких груп може бути декілька, вони нумеруються; в даному випадку частина буде доступна в змінній під номером один — $1.
$1 = (ець|чага)
З круглими дужками розібралися. Переходимо до квадратних. Коли ми розглядали символьні класи, поряд з кожним шаблоном типу d одному символу-ціфрі відповідає еквівалент формату — [0-9], що логічно означає те ж саме. Але, зрозуміло, варіант зі слешем зручніше і запам’ятовується легше, ніж наприклад [ \t\n\r\f\v] – символ пробілу — легше записати так — \s.
Іноді необхідно створити свій власний користувальницький клас . Це можливо завдяки квадратним дужках і переліком всіляких символів, які можуть зустрітися. Припустимо, різні закінчення слова Вода – Вод [аеиу] або відповідність різним відмінками.
Квадратні дужки також можуть зустрічатися зі знаком ^ одразу після відкриваючої дужки. Такий дует виконує «негативну» функцію. Тобто під час запиту [^Молодець] знайдуться далеко не хвалебні рядки. Так працює і з символьними класами, наприклад [^0-9], буде шукати відповідності протилежні, тобто все, що не відповідає цифрам в дужках.
Ну і наостанок згадаємо про функції фігурних дужок — {}. Їх використовують за необхідності вказати кількість повторень символу, що стоїть перед дужками. Ми детально це розглядали в розділі квантіфікатори.
Метасимвол АБО в квадратних дужках не працює.
Прапори
Ми вивчили достатню кількість спеціальних символів і навчилися будувати регулярні вирази, але забули про фундаментальну концепції — прапори.
Прапори — це додаткові надбудови для шаблону регулярного виразу, які розширюють їх функції. Прапори вказуються після регулярного виразу (порядок прапорів значення не має).
Розглянемо основні прапори в регулярних виразах:
- g (global) ― не повертає результат після першого збігу, а продовжує пошук з кінця попереднього збігу.
- m (multi line) ― з таким прапором, оператори ^ і $ викличуть збіг на початку і кінці рядка введення (line), замість рядка цілком (string).
- i (insensitive) ― робить вираз регістронезалежним (наприклад, /aBc/i відповідає AbC).
Якщо з останнім прапором все більш-менш зрозуміло, то перші два давайте розглянемо на прикладі.
Припустимо, у нас є рядок типу:
1‑е місце: № 7 ― Тінкі-Вінкі.
2‑е місце: № 13 ― Лала.
3‑е місце: № 4 ― По.
І нам потрібно знайти:
- Всі цифриШаблон \d, за замовчуванням, видасть нам перший збіг, тобто «1». Щоб знайти всі присутні в тексті цифри необхідно підключити прапор глобального пошуку — /\d/g, який видасть нам всі збіги.
- Тільки цифри на початку рядкаДодати якір початку рядка буде недостатньо. Шаблон ^\d видасть тільки «1», глобальний прапор тут не допоможе. И це не помилка. Чому так? Тому що, початок рядка в нашому прикладі дійсний тільки перед одиницею, а кінець, відповідно, — в самому кінці рядка:^1–е место: № 7 ― Тінки-Вінки
2‑е место: № 13 ― Лала
3‑е место: № 4 ― По$Щоб вважати кожне перенесення рядка на нову лінію «початком», потрібно скористатися прапором многострокового режиму m: шаблону /^\d/gm відповідатимуть «1», «2» и «3», адже рядок такий шаблон буде бачити так:
^1е место: № 7 ― Тинки-Винки$
^2е место: № 13 ― Лала$
^3е место: № 4 ― По$Аналогічно, можна шукати символи з кінця рядка і ліній.
В сервісах, якими ми користуємося, за замовчуванням виконується глобальний пошук без урахування регістру, тому з прапорами будемо зустрічатися не часто. Щоб детально ознайомитися з їх функціями, пропонуємо познайомитися з прикладом на Regex101.
Застосування на практиці
Прилад №1
На сайті є 2 thank you page:
- https://inweb.ua/thank-you-page/
- https://inweb.ua/order-success/
Нам потрібно враховувати їх відвідування, як виконання однієї мети в Google Analytics. Для цього вибираємо в GA мету відвідання сторінки і вказуємо регулярний вираз:
thank-you-page|order-success
Приклад №2
Ми впровадили новий дизайн картки товару і хочемо дізнатися, як це вплинуло на кількість трафіку. Таких сторінок кілька та їх url-адреси відрізняються тільки цифрою в кінці:
https://inweb.ua/category-34/best-iphone-ever4
Подивитись, як змінівся трафік на сторінці товарів, ми можемо за сторінкою входу в Google Analytics, вікористовуючі прості регулярні вирази:
[0-9]$
А якщо ми хочемо виділити все url-адреси товарів в таблиці — краще використовувати:
.*[0-9]$
Приклад №3
Є перелік url-адрес з відносними посиланнями, наприклад:</>
/category/tovar/
/contacts/
Завдання: зробити абсолютно всі url-адреси абсолютними з доменом https://inweb.ua/
За допомогою регулярного виразу ^\/ ми можемо виділити перший слеш в рядку і здійснити глобальну заміну на потрібний нам домен.
Приклад №4
Припустимо, є документ з 50 000 рядків, серед них є порожні, які потрібно видалити. Для вирішення завдання можна виділити порожні рядки за допомогою ^ \ s * $ і здійснити заміну.
Приклад №5
Є 50 000 номерів телефонів, в 1% з них містять більше інформації, яку потрібно прибрати, наприклад:
- +380001234567 факс
- +380001234567 – Валера
- +380001234567(Бухгалтерия)
- +380001234567 Юра Колокол
Формат, який нам потрібен, виглядає так: +380001234567.
За допомогою регулярного виразу (-.*|\(.*|.[A-z].*|[А-я].*) виокремлюємо всі варіанти додаткової інформації, яку потрібно видалити та замінити.
Приклад №6
У документі з текстом є подвійні та потрійні пробіли, наприклад:
Ми збираємо інформацію, коли ви входите на сайт, заходите на свій аккаунт і / або виходите зі свого облікового запису. Інформація включає ваше ім’я, адресу електронної пошти, номер телефону. Крім того, ми автоматично реєструємо ваш комп’ютер і браузер, що включають IP, ПО і Апаратні дані, а також адресу запитуваної сторінки.
Для того щоб їх прибрати використовуємо регулярний вираз \s{2,} і замінюємо на один пробіл.
Довідкові матеріали по темі
- Зручний сервіс для перевірки працездатності регулярних виразів.
- Шпаргалка за регулярними виразами.
- Як новачкові розібратися в регулярних виразах.
- Складний тест на знання регулярних виразів.
- Приклади регулярних виразів.