Регулярний вираз (або regex) - це послідовність символів, яку ми можемо використовувати, щоб знаходити та змінювати певні елементи в рядках тексту (англ. string). Отже, ми можемо:
Ця концепція присвячена використанню регулярних виразів у JavaScript. Якщо ми хочемо дізнатися, як писати регулярні вирази, Eloquent JavaScript може стати добрим джерелом.
💡 Варіант регулярних виразів, який підтримує JavaScript, є частиною стандарту ECMA-262 для цієї мови. Це означає, що нам не потрібно турбуватися про сумісність із конкретними браузерами.
У JavaScript регулярні вирази здебільшого записують у форматі /pattern/modifiers, де «pattern» - це основний regex, а «modifiers» - низка символів, які ми можемо додати, щоб указати особливі опції (наче суперсили).
Тим не менш, є два способи створити регулярний вираз:
const regex = /[a-z]/;
const regex = new RegExp('[a-z]');
В обох випадках JavaScript створює з регулярного виразу обʼєкт. Рекомендовано типово використовувати незмінні вирази разом із літералом.
Конструктор RegExp можна використати у випадках, коли регулярний вираз змінюватиметься або коли ми його ще не знаємо (наприклад, коли він надходить із введення).
Регулярні вирази мають необовʼязкові суперсили під назвою flags, які вмикають додаткові можливості. Ці прапорці можна використовувати окремо або разом, у будь-якому порядку, і вони входять до складу регулярного виразу.
Ось деякі з найуживаніших:
/g - глобальний пошук/i - ігнорування регістру/m - багаторядковий пошукОсь простий приклад:
const re = /home/gi;
const str = 'Home, sweet home.';
str.match(re);
// => ["Home", "home"]
Символ g дозволяє нам знайти всі можливі збіги в рядку тексту. Без цієї можливості JavaScript вилучив би лише перший збіг Home.
Прапорець ігнорування регістру /i дає нам гнучкість під час пошуку. Завдяки йому неважливо, записано те, що ми шукаємо, у UPPERCASE чи lowercase.
Коли ми використовуємо конструктор RegExp, синтаксис додавання прапорців інший. У цьому разі достатньо передати прапорці другим аргументом.
Коли ми поєднуємо регулярні вирази з вбудованими функціями JavaScript, ми отримуємо потужні способи роботи з даними в рядках тексту.
Метод test() - чудовий спосіб пошуку та перевірки, чи є шукане значення в заданому рядку тексту. Він повертає булеве значення (англ. Boolean), true або false.
Метод match() видобуває збіг регулярного виразу із заданого рядка тексту. Він повертає масив з інформацією та збігами.
Коли використовувати той чи інший? test() доречний, коли потрібен швидкий спосіб перевірити значення в рядку тексту, а match() - коли потрібно скористатися цим значенням або дізнатися більше про збіг.
Метод test() виконує пошук збігу між регулярним виразом і заданим рядком тексту. Повертає правду або неправду.
const str = 'It is difficult to test if you have a virus';
const result = /virus$/.test(str);
console.log(result);
// => true
Гаразд, але що, якщо ми хочемо отримати самі значення з пошуку регулярного виразу?
Замість того щоб повертати лише булеве значення, метод match() дає нам корисний масив, вміст якого залежить від наявності або відсутності знайдених збігів.
Так ми можемо і шукати, і видобувати інформацію з будь-якого рядка тексту. Наприклад:
const funnyQuote =
'If you see someone crying, ask if it is because of their haircut.';
const regex1 = /someone/;
const regex2 = /happy/;
funnyQuote.match(regex1);
// => ["someone", index: 3, input: "If you see someone crying, ask if it is because of their haircut.", groups: undefined]
funnyQuote.match(regex2);
// => null
Коли встановлено прапорець глобального пошуку /g, метод повертає не лише єдиний збіг разом із корисною інформацією, як-от індекс чи вхідний рядок, а всі входження, наявні в масиві:
const funnyQuote =
'If you see someone crying, ask if it is because of their haircut.';
const regex3 = /if/gi;
funnyQuote.match(regex3);
// => ["If", "if"];
Метод replace() у JavaScript дозволяє нам знайти значення в заданому рядку тексту й замінити його новим значенням.
string.replace(searchValue, newValue);
Значенням для пошуку під час заміни може бути окремий рядок тексту або регулярний вираз.
let string = 'I like dogs!';
let result = string.replace('dogs', 'cats');
let string = 'I would love to travel to Japan';
let result = string.replace(/Japan/g, 'Hawaii');
Крім того, на місце заміни можна підставити функцію, щоб додатково змінити кожне значення.
let text = 'Say hello to the chatbot.';
let result = text.replace(/chatbot|hello/gi, function (word) {
return word.toUpperCase();
});
// => "Say HELLO to the CHATBOT"
💡 Зрештою, поєднання регулярних виразів і методу
replace()- динамічніший спосіб заміни елементів. Використання окремого рядка тексту має свої обмеження.
Метод split() у JavaScript - це інший спосіб використовувати регулярні вирази для роботи з рядками тексту.
Так ми використовуємо regex, щоб розділити заданий рядок тексту за розпізнаною закономірністю, наприклад str.split(/[,.\s]/). Ця закономірність використовується як separator.
const str = 'hello,user.how are.you';
const result = str.split(/[,.\s]/);
console.log(result);
// => ['hello', 'user', 'how', 'are', 'you']
Щодо швидкодії, обидва способи створюють обʼєкт RegExp. Основна різниця в тому, як часто компілюється регулярний вираз:
Regular Expression Literal: один раз під час початкового розбору й компіляції кодуRegExp(): щоразу, коли створюється новий обʼєкт.Використання синтаксису літерала може бути кращим варіантом не лише через швидкодію, а й через простоту та читабельність. Докладніше дивіться в обговоренні на Stack Overflow.
RegExp(), потрібно також екранувати лапки та подвійно екранувати зворотні слеші. Це робить регулярні вирази, які й без того важко читати й розуміти, ще складнішими.