Регулярні вирази
Регулярні вирази — це патерни, які застосовуються для пошуку збігів з комбінаціями символів у рядках. У JavaScript регулярні вирази також є об'єктами. Ці патерни використовуються методами об'єкта RegExp
: exec()
і test()
, а також методами String
: match()
, matchAll()
, replace()
, replaceAll()
, search()
і split()
.
Цей розділ описує регулярні вирази у JavaScript.
Створення регулярного виразу
Сконструювати регулярний вираз можна одним із двох способів:
-
Використавши літерал регулярного виразу, який складається з патерну, оточеного скісними рисками, як показано нижче:
const re = /ab+c/;
Літерали регулярного виразу забезпечують компіляцію виразу під час завантаження сценарію. Якщо регулярний вираз залишається незмінним, такий варіант може покращити швидкодію.
-
Або ж викликавши конструктор об'єкта
RegExp
, як показано:const re = new RegExp("ab+c");
Використання конструктора забезпечує компіляцію регулярного виразу під час виконання програми. Конструктор слід використовувати, якщо наперед невідомо, чи патерн буде змінюватись, або ж якщо патерн іще невідомий і його буде отримано пізніше з інших джерел (наприклад, введено користувачем).
Написання патерну регулярного виразу
Патерн регулярного виразу складається з простих символів, як от /abc/
, або ж з поєднання простих і спеціальних символів, як /ab*c/
чи /Chapter (\d+)\.\d*/
.
Останній приклад містить дужки, які використовуються як вказівка до запам'ятовування.
Зіставлення, виконане з цією частиною патерну, буде запам'ятоване для пізнішого використання, як це описано в частині Застосування груп.
Примітка: Якщо ви вже знайомі з формами регулярних виразів, зверніть увагу на шпаргалку, якщо потрібно швидко знайти якийсь конкретний патерн чи конструкцію.
Застосування простих патернів
Прості патерни складаються з символів, яким треба знайти прямі відповідники. Наприклад, патерн /abc/
збігається з комбінацією символів у рядках тільки коли трапляється саме ця послідовність – "abc"
(всі букви разом, і саме в такому порядку). Такий збіг трапився б у двох рядках: "Hi, do you know your abc's?"
і "The latest airplane designs evolved from slabcraft."
. В обох випадках трапляється збіг з підрядком "abc"
. Не існує збігів у рядку "Grab crab"
, і хоча він містить підрядок "ab c"
, в ньому не зустрічається точна послідовність "abc"
.
Застосування спеціальних символів
Якщо пошук збігу потребує чогось більшого, аніж просто прямого відповідника, як от знаходження однієї чи більше літер «b», чи знаходження пробілу, слід включати в патерн спеціальні символи. Наприклад, щоб знайти збіг для одної літери "a"
, після якої є нуль або більше літер "b"
, а за ними літера "c"
, використовується патерн /ab*c/
: зірочка *
після "b"
означає "наявність попереднього елемента в кількості 0 чи більше одиниць. В рядку "cbbabbbbcdebc"
цей патерн покаже збіг з підрядком "abbbbc"
.
Наступні сторінки містять списки різних спеціальних символів, розбитих на категорії, з описами та прикладами.
- Посібник Перевірки
Перевірки включають межі, які позначають початки й закінчення слів та рядків, та інші патерни, котрі якимось чином вказують, що збіг можливий (включно з випереджувальними, ретроспективними та умовними виразами).
- Посібник Класи символів
Розрізняють різні типи символів. Наприклад, розрізнення літер та цифр.
- Посібник Групи й зворотні посилання
Групи групують декілька патернів як єдине ціле, а групи захоплення надають додаткову інформацію вкладеного збігу, коли патерн регулярного виразу зіставляється з рядком. Зворотні посилання посилаються на попередньо захоплену групу в тому самому регулярному виразі.
- Посібник Квантори
Вказують кількість символів чи виразів для збігу.
Нижче наведено єдину таблицю всіх спеціальних символів, які можна використовувати в регулярних виразах:
Символи / конструкції | Відповідна стаття |
---|---|
[xyz] , [^xyz] , . ,
\d , \D , \w , \W ,
\s , \S , \t , \r ,
\n , \v , \f , [\b] ,
\0 , \cX , \xhh ,
\uhhhh , \u{hhhh} ,
x|y
|
|
^ , $ , \b , \B ,
x(?=y) , x(?!y) , (?<=y)x ,
(?<!y)x
|
|
(x) , (?<Name>x) , (?:x) ,
\n , \k<Name>
|
|
x* , x+ , x? ,
x{n} , x{n,} ,
x{n,m}
|
Примітка: Доступна також більша шпаргалка (що містить лише витяги зі статей окремих спецсимволів).
Екранування
Якщо потрібно вжити будь-який спеціальний вираз буквально (наприклад, шукаючи власне символ "*"
), його потрібно екранувати шляхом додавання зворотного скосу перед ним.
Зокрема, щоб знайти літеру "a"
, за якою слідує "*"
, слідом за яким літера "b"
, треба вжити патерн /a\*b/
: зворотний скіс «екранує» "*"
, роблячи її просто знаком і нейтралізуючи спеціальне значення.
Аналогічно, якщо під час написання літерала регулярного виразу потрібно знайти збіг із символом скосу ("/"), слід його екранувати (інакше він означатиме кінець патерну).
Для прикладу, щоб знайти рядок "/example/", за яким слідує одна чи більше букв алфавіту, слід використати патерн /\/example\/[a-z]+/i
— зворотна коса перед кожною косою робить їх просто символами.
Щоб знайти збіг зворотного скосу буквально, слід його екранувати.
Наприклад, щоб знайти рядок "C:\", де «C» може бути будь-якою літерою, слід використати патерн /[A-Z]:\\/
: перший зворотний скіс екранує наступний після нього, тож вираз шукатиме буквально одну зворотну скісну риску.
Використовуючи конструктор RegExp
з рядковим літералом, пам'ятайте, що зворотний скіс — це екранувальний символ в рядкових літералах. І щоб застосувати його в регулярному виразі, слід спершу його екранувати на рівні рядкового літерала. /a\*b/
та new RegExp("a\\*b")
створюють один і той самий вираз, який шукатиме літеру "a" з символом за нею "*" і літерою "b" після них.
Якщо екранувальні рядки ще не входять в готовий патерн, їх можна додати за допомогою String.prototype.replace()
:
function escapeRegExp(string) {
return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); // $& означає цілий рядок, який збігся з патерном
}
Літера "g" після регулярних виразів — це опція або позначка, що виконує глобальний пошук, перебираючи рядок цілком і повертаючи всі можливі збіги. Це пояснено в деталях нижче, в розділі Поглиблений пошук з позначками.
Чому це не вбудовано всередину JavaScript? Існує пропозиція додати таку функцію до RegExp.
Застосування дужок
Дужки навколо будь-якої частини патерну регулярного виразу призводять до того, що ця частина знайденого підрядка буде збережена окремо. До збереженого підрядка можна потім знову звернутися і використати для інших цілей. Більше деталей є в розділі Групи та зворотні посилання.
Застосування регулярних виразів у JavaScript
Регулярні вирази з методами об'єкта RegExp
, наприклад, test()
і exec()
, а також із методами String
: match()
, matchAll()
, replace()
, replaceAll()
, search()
і split()
.
Метод | Опис |
---|---|
exec() |
Виконує пошук збігу в рядку. Повертає масив з інформацією або null , якщо збігів не знайдено. |
test() |
Перевіряє рядок на збіг. Повертає true або false . |
match() |
Повертає масив, що містить всі знайдені збіги, включно з групами захоплення, або ж null , якщо збігів не знайдено. |
matchAll() |
Повертає ітератор, що містить всі знайдені збіги, включно з групами захоплення. |
search() |
Перевіряє рядок на наявність збігів. Повертає індекс збігу, або -1 , якщо пошук завершився невдачею. |
replace() |
Виконує пошук збігу в рядку і заміняє знайдену частину рядка переданим рядком для заміни. |
replaceAll() |
Виконує пошук всіх збігів у рядку і заміняє знайдені частини рядка переданим рядком для заміни. |
split() |
Використовує регулярний вираз або фіксований рядок, щоб розбити початковий рядок на масив підрядків. |
Якщо потрібно визначити, чи патерн присутній в рядку, використовуйте методи test()
або search()
. Для отримання докладнішої інформації (вкупі з повільнішим виконанням) застосовуйте методи exec()
чи match()
.
Якщо використовується метод exec()
чи match()
, і знаходиться збіг, ці методи повертають масив і оновлюють властивості пов'язаного об'єкта регулярного виразу, а також властивості глобального об'єкта RegExp
. Якщо збіг знайти не вдалося, то метод exec()
поверне null
(який, зрештою, зводиться до false
).
В наступному прикладі сценарій шукає збіги в рядку за допомогою методу exec()
.
const myRe = /d(b+)d/g;
const myArray = myRe.exec("cdbbdbsbz");
А в цьому сценарії — альтернативний варіант створення масиву myArray
, на випадок якщо вам не потрібен доступ до властивостей самого регулярного виразу:
const myArray = /d(b+)d/g.exec("cdbbdbsbz");
// так само, як і з "cdbbdbsbz".match(/d(b+)d/g); однак,
// "cdbbdbsbz".match(/d(b+)d/g) виводить [ "dbbd" ]
// /d(b+)d/g.exec('cdbbdbsbz') виводить [ 'dbbd', 'bb', index: 1, input: 'cdbbdbsbz' ]
(Дивіться більше інформації цю різницю в поведінці у частині Застосування позначки глобального пошуку з exec()
.)
Якщо ж потрібно сконструювати регулярний вираз із рядка, ось іще одна альтернатива:
const myRe = new RegExp("d(b+)d", "g");
const myArray = myRe.exec("cdbbdbsbz");
В цих сценаріях пошук збігів успішно завершується, повертає масив результатів і оновлює властивості, наведені в таблиці нижче:
Об'єкт | Властивість або індекс | Опис | В цьому прикладі |
---|---|---|---|
myArray |
Рядок, що збігся, а також всі запам'ятовані підрядки. | ['dbbd', 'bb', index: 1, input: 'cdbbdbsbz'] |
|
index |
Індекс позиції (від 0) збігу у вхідному рядку. | 1 |
|
input |
Вхідний рядок. | 'cdbbdbsbz' |
|
[0] |
Символи з останнього збігу. | 'dbbd' |
|
myRe |
lastIndex |
Індекс, з якого почнеться пошук наступного збігу. (Ця властивість встановлюється лише якщо регулярний вираз використовує опцію «g», описану в частині Поглиблений пошук з позначками.) | 5 |
source |
Текст патерну. Оновлюється в момент створення регулярного виразу, не виконання. | 'd(b+)d' |
Як було показано у другому варіанті цього прикладу, можна використовувати регулярні вирази, створені об'єктним конструктором без присвоєння його змінній. Однак у цьому випадку кожний новий виклик створюватиме новий регулярний вираз. З цієї причини, якщо ця форма використовується без присвоєння виразу змінній, неможливо потім отримати доступ до властивостей цього виразу. Наприклад, припустімо, у нас є такий сценарій:
const myRe = /d(b+)d/g;
const myArray = myRe.exec("cdbbdbsbz");
console.log("Поле lastIndex має значення " + myRe.lastIndex);
// "Поле lastIndex має значення 5"
Однак, якщо натомість у нас є такий сценарій:
const myArray = /d(b+)d/g.exec("cdbbdbsbz");
console.log("Поле lastIndex має значення " + /d(b+)d/g.lastIndex);
// "Поле lastIndex має значення 0"
Вирази /d(b+)d/g
у двох інструкціях вище — це насправді різні об'єкти регулярного виразу, і тому вони містять різні значення їхньої властивості lastIndex
. Якщо потрібно доступитися до властивостей регулярного виразу, створеного об'єктним конструктором, слід спершу присвоїти його змінній.
Поглиблений пошук з позначками
Регулярні вирази мають необов'язкові опції, що дає змогу використовувати таку функціональність, як глобальний пошук чи пошук без врахування регістру літер. Ці опції можна використовувати окремо або разом, у будь-якому порядку, і вони входять в сам регулярний вираз.
Позначка | Опис | Відповідна властивість |
---|---|---|
d |
Згенерувати індекси для збігів підрядків. | hasIndices |
g |
Глобальний пошук. | global |
i |
Пошук, нечутливий до регістру. | ignoreCase |
m |
Дозволяє ^ та $ давати збіг поруч з символами нового рядка. |
multiline |
s |
Дозволяє символові . давати збіг з символами нового рядка. |
dotAll |
u |
"Unicode"; сприймає патерн як послідовність кодових точок Unicode. | unicode |
v |
Оновлена версія режиму u , з більшою кількістю можливостей Unicode. |
unicodeSets |
y |
Виконує «липкий» пошук, який починає пошук збігів з поточної позиції цільового рядка. | sticky |
Щоб включити позначку в регулярний вираз, використовується такий синтаксис:
const re = /pattern/flags;
або
const re = new RegExp("pattern", "flags");
Зауважте, що ці опції — це невідокремна частина регулярного виразу. Їх неможливо додати чи прибрати потім.
Наприклад, re = /\w+\s/g
створює регулярний вираз, що шукає одну або більше літер, за якими слідує пробіл, і він виконує цей пошук по всьому рядку.
const re = /\w+\s/g;
const str = "fee fi fo fum";
const myArray = str.match(re);
console.log(myArray);
// ["fee ", "fi ", "fo "]
Можна замінити цей рядок:
const re = /\w+\s/g;
...на такий:
const re = new RegExp("\\w+\\s", "g");
...і отримати такий самий результат.
Позначка m
використовується для вказання, що багаторядковий вхідний текст має сприйматись як декілька різних рядків. Якщо використано прапорець m
, символи ^
і $
позначають відповідно початок та кінець кожного рядка всередині вхідної стрічки замість початку і кінця стрічки в цілому.
Застосування позначки глобального пошуку з exec()
Метод RegExp.prototype.exec()
із позначкою g
ітеративно поверне кожен збіг та його позицію.
const str = "fee fi fo fum";
const re = /\w+\s/g;
console.log(re.exec(str)); // ["fee ", index: 0, input: "fee fi fo fum"]
console.log(re.exec(str)); // ["fi ", index: 4, input: "fee fi fo fum"]
console.log(re.exec(str)); // ["fo ", index: 7, input: "fee fi fo fum"]
console.log(re.exec(str)); // null
Натомість метод String.prototype.match()
поверне усі збіги відразу, втім, без їх позицій.
console.log(str.match(re)); // ["fee ", "fi ", "fo "]
Використання юнікодних регулярних виразів
Прапорець "u" використовується для створення "юнікодних" регулярних виразів; це такі регулярні вирази, котрі підтримують пошук збігів у юнікодному тексті. Це здебільшого досягнуто шляхом використання екранування юнікодних властивостей. Наприклад, наступний регулярний вираз може застосовуватися для пошуку збігу в довільному юнікодному "слові":
/\p{L}*/u;
Регулярні вирази Unicode також мають інакшу логіку виконання. Стаття RegExp.prototype.unicode
містить подробиці на цю тему.
Приклади
Примітка: Декілька прикладів також доступні:
- На довідникових сторінках для
exec()
,test()
,match()
,matchAll()
,search()
,replace()
,split()
- У статтях посібника: класи символів, перевірки, групи та зворотні посилання, квантори
Застосування спеціальних символів для перевірки вводу
В цьому прикладі користувач має ввести телефонний номер. Коли користувач натискає кнопку "Check", сценарій перевіряє правильність номера. Якщо номер коректний (збігається з послідовністю символів, заданою регулярним виразом), то сценарій показує повідомлення з подякою користувачеві та підтвердженням номера. Якщо номер некоректний, то сценарій інформує користувача про те, що номер введено невірно.
Регулярний вираз шукає:
- Початок рядка з даними:
^
- Далі три цифрових знаки
\d{3}
АБО|
ліва дужка\(
з трьома цифрами за нею\d{3}
, закритими правою дужкою\)
, і це все об'єднано в групу (без захоплення)(?:)
- Далі один дефіс, скісна риска або десяткова крапка, що захоплено в групу
()
- Далі іще три цифри
\d{3}
- Далі збіг, запам'ятований у першій захопленій групі
\1
- Далі іще чотири цифри
\d{4}
- І за ними кінець рядка з даними:
$
Подія click
, котра спрацьовує під час натискання користувачем клавіші Enter, встановлює значення phoneInput.value
.
HTML
<p>
Введіть ваш номер телефону (з кодом населеного пункту) та натисність
"Перевірити".
<br />
Очікуваний формат номера: ###-###-####.
</p>
<form id="form">
<input id="phone" />
<button type="submit">Перевірити</button>
</form>
<p id="output"></p>
JavaScript
const form = document.querySelector("#form");
const input = document.querySelector("#phone");
const output = document.querySelector("#output");
const re = /^(?:\d{3}|\(\d{3}\))([-/.])\d{3}\1\d{4}$/;
function testInfo(phoneInput) {
const ok = re.exec(phoneInput.value);
output.textContent = ok
? `Дякую, ваш номер телефону – ${ok[0]}`
: `${phoneInput.value} не є телефонним номером із кодом населеного пункту!`;
}
form.addEventListener("submit", (event) => {
event.preventDefault();
testInfo(input);
});
Результат
Інструменти
- RegExr
Онлайн-інструмент для вивчення, побудови та тестування регулярних виразів.
- Regex tester
Онлайн-інструмент для побудови та зневадження регулярних виразів
- Regex interactive tutorial
Онлайнові інтерактивні підручники, шпаргалка та ігровий майданчик.
- Regex visualizer
Візуальний онлайн-інструмент для тестування регулярних виразів.