diff --git a/9-regular-expressions/01-regexp-introduction/article.md b/9-regular-expressions/01-regexp-introduction/article.md index e5555e344..788dd67ca 100644 --- a/9-regular-expressions/01-regexp-introduction/article.md +++ b/9-regular-expressions/01-regexp-introduction/article.md @@ -1,26 +1,26 @@ -# Вступ: шаблони та прапори +# Вступ: шаблони та прапорці -Регулярні вирази – потужний засіб пошуку та заміни тексту в рядках. +Регулярні вирази -- потужний засіб пошуку та заміни тексту в рядках. В JavaScript регулярні вирази реалізовані окремим об’єктом [RegExp](mdn:js/RegExp) та інтегровані у методи рядків. ## Регулярні вирази -Регулярний вираз (він же "регексп", "регулярка" або просто "рег"), складається з *шаблону* (також кажуть "патерн") і необов’язкових *прапорів*. +Регулярний вираз (він же "регексп", "регулярка" або просто "рег"), складається з *шаблону* (також кажуть "патерн") і необов’язкових *прапорців*. Існує два синтаксиси для створення регулярного виразу. "Довгий" синтаксис: ```js -regexp = new RegExp("шаблон", "прапори"); +regexp = new RegExp("шаблон", "прапорці"); ``` Та "короткий" синтаксис, в якому використовуються слеши `"/"`: ```js -regexp = /шаблон/; // без прапорів -regexp = /шаблон/gmi; // з прапорами g,m та i (будуть описані далі) +regexp = /шаблон/; // без прапорців +regexp = /шаблон/gmi; // з прапорцями g,m та i (будуть описані далі) ``` Слеши `pattern:/.../` говорять JavaScript про те, що це регулярний вираз. Вони відіграють таку саму роль, як і лапки для позначення рядків. @@ -29,7 +29,7 @@ regexp = /шаблон/gmi; // з прапорами g,m та i (будуть о Основна різниця між цими двома синтаксами полягає в тому, що слеши `/.../` не допускають жодних вставок змінних (на зразок тих, що прописуються через `${...}`). Вони повністю статичні. -Слеши використовуються, коли ми на момент написання коду точно знаємо, яким буде регулярний вираз - і це більшість ситуацій. А `new RegExp` - коли ми хочемо створити регулярний вираз "на льоту" з динамічно згенерованого рядка, наприклад: +Слеши використовуються, коли ми на момент написання коду точно знаємо, яким буде регулярний вираз -- і це більшість ситуацій. А `new RegExp` -- коли ми хочемо створити регулярний вираз "на льоту" з динамічно згенерованого рядка, наприклад: ```js let tag = prompt("Який тег ви хочете знайти?", "h2"); @@ -37,17 +37,17 @@ let tag = prompt("Який тег ви хочете знайти?", "h2"); let regexp = new RegExp(`<${tag}>`); // те саме, що /

/ при відповіді "h2" на запит вище ``` -## Прапори +## Прапорці -Регулярні вирази можуть мати прапори, які впливають на пошук. +Регулярні вирази можуть мати прапорці, які впливають на пошук. У JavaScript їх всього шість: `pattern:i` -: З цим прапором пошук не залежить від регістру: немає різниці між `A` та `a` (див. приклад нижче). +: З цим прапорцем пошук не залежить від регістру: немає різниці між `A` та `a` (див. приклад нижче). `pattern:g` -: З цим прапором пошук шукає всі збіги, без нього - лише перше. +: З цим прапорцем пошук шукає всі збіги, без нього -- лише перший. `pattern:m` : Багаторядковий режим (розглядається в розділі ). @@ -56,39 +56,39 @@ let regexp = new RegExp(`<${tag}>`); // те саме, що /

/ при від : Вмикає режим "dotall", при якому крапка `pattern:.` може відповідати символу нового рядка `\n` (розглядається у розділі ). `pattern:u` -: Вмикає повну підтримку Юнікоду. Прапор дозволяє коректну обробку сурогатних пар (докладніше про це у розділі ). +: Вмикає повну підтримку Юнікоду. Цей прапорець дозволяє коректну обробку сурогатних пар (докладніше про це у розділі ). `pattern:y` : Режим пошуку на конкретній позиції в тексті (описаний у розділі ) ```smart header="Кольорові позначення" -Тут і далі в тексті використовується наступна колірна схема: +Тут і далі в тексті використовується наступна схема кольорів: -- регулярний вираз - `pattern:червоний` +- регулярний вираз -- `pattern:червоний` - рядок (там, де відбувається пошук) -- `subject:синій` - результат -- `match:зелений` ``` ## Пошук: str.match -Як вже згадувалося, використання регулярних виразів інтегровано у методи рядків. +Як вже згадувалося, регулярні вирази можна використовувати в методах рядків. Метод `str.match(regexp)` для рядка `str` повертає збіги з регулярним виразом `regexp`. У нього є три режими роботи: -1. Якщо в регулярного виразу є прапор `pattern:g`, то він повертає масив всіх збігів: +1. Якщо в регулярного виразу є прапорець `pattern:g`, то він повертає масив всіх збігів: ```js run let str = "За Вас правда, за вас слава і воля святая!"; alert(str.match(/вас/gi)); // Вас, вас (масив із 2х підрядків-збігів) ``` - Зверніть увагу: знайдено як `match:Вас` так і `match:вас`, завдяки прапору `pattern:i`, який робить регулярний вираз реєстронезалежним. + Зверніть увагу: знайдено як `match:Вас` так і `match:вас`, завдяки прапорцю `pattern:i`, який робить регулярний вираз незалежним від регістру. -2. Якщо такого прапора немає, то повертається лише перший збіг у вигляді масиву, в якому за індексом `0` знаходиться збіг, і є властивості з додатковою інформацією про нього: +2. Якщо такого прапорця немає, то повертається лише перший збіг в масиві, де за індексом `0` знаходиться сам збіг, і є деякі властивості з додатковою інформацією про нього: ```js run let str = "За Вас правда, за вас слава і воля святая!"; - let result = str.match(/вас/i); // без прапора g + let result = str.match(/вас/i); // без прапорця g alert(result[0]); // Вас (перший збіг) alert(result.length); // 1 @@ -99,7 +99,7 @@ let regexp = new RegExp(`<${tag}>`); // те саме, що /

/ при від ``` У цьому масиві можуть бути інші індекси, крім `0`, якщо частина регулярного виразу виділена в дужки. Ми розберемо це у розділі . -3. І, нарешті, якщо збігів немає, то, незалежно від наявності прапора `pattern:g`, повертається `null`. +3. І, нарешті, якщо збігів немає, то, незалежно від наявності прапорця `pattern:g`, повертається `null`. Це дуже важливий аспект. За відсутності збігів повертається не порожній масив, а саме `null`. Якщо про це забути, можна легко припуститися помилки, наприклад: @@ -121,16 +121,16 @@ let regexp = new RegExp(`<${tag}>`); // те саме, що /

/ при від ## Заміна: str.replace -Метод `str.replace(regexp, replacement)` замінює збіги з `regexp` у рядку `str` на `replacement` (всі збіги, якщо є прапор `pattern:g`, інакше тільки перше). +Метод `str.replace(regexp, replacement)` замінює збіги з `regexp` у рядку `str` на `replacement` (всі збіги, якщо є прапорець `pattern:g`, інакше тільки перше). Наприклад: ```js run -// без прапора g -alert( "Ми будемо, ми будемо".replace(/ми/i, "Я") ); // Я будемо, ми будемо +// без прапорця g +alert( "We will, we will".replace(/we/i, "I") ); // I will, we will -// з прапором g -alert( "Ми будемо, ми будемо".replace(/ми/ig, "Я") ); // Я будемо, Я будемо +// з прапорцем g +alert( "We will, we will".replace(/we/ig, "I") ); // I will, I will ``` У рядку заміни `replacement` ми можемо використовувати спеціальні комбінації символів для вставки фрагментів збігу: @@ -140,7 +140,7 @@ alert( "Ми будемо, ми будемо".replace(/ми/ig, "Я") ); // Я |`$&`|вставляє всі знайдені збіги| |$`|вставляє частину рядка до збігу| |`$'`|вставляє частину рядка після збігу| -|`$n`|якщо `n` це 1-2 значне число, вставляє вміст n-ї скобочної групи регулярного виразу, більше у розділі | +|`$n`|якщо `n` це 1-2 значне число, вставляє вміст n-ої скобочної групи регулярного виразу, більше у розділі | |`$`|вставляє вміст скобочної групи з ім'ям `name`, також вивчимо у розділі | |`$$`|вставляє символ `"$"` | @@ -167,8 +167,8 @@ alert( regexp.test(str) ); // true ## Підсумки -- Регулярний вираз складається з шаблону і необов’язкових прапорів: `pattern:g`, `pattern:i`, `pattern:m`, `pattern:u`, `pattern:s`, `pattern:y`. -- Без прапорів та спеціальних символів, які ми вивчимо пізніше, пошук за регулярним виразом аналогічний пошуку підрядка. -- Метод `str.match(regexp)` шукає збіги: всі, якщо є прапор `pattern:g`, інакше тільки перший. -- Метод `str.replace(regexp, replacement)` замінює збіги з `regexp` на `replacement`: всі, якщо у регулярного виразу є прапор `pattern:g`, інакше тільки перший. +- Регулярний вираз складається з шаблону і необов’язкових прапорців: `pattern:g`, `pattern:i`, `pattern:m`, `pattern:u`, `pattern:s`, `pattern:y`. +- Без прапорців та спеціальних символів, які ми вивчимо пізніше, пошук за регулярним виразом аналогічний пошуку підрядка. +- Метод `str.match(regexp)` шукає збіги: всі, якщо є прапорець `pattern:g`, інакше тільки перший. +- Метод `str.replace(regexp, replacement)` замінює збіги з `regexp` на `replacement`: всі, якщо у регулярного виразу є прапорець `pattern:g`, інакше тільки перший. - Метод `regexp.test(str)` повертає `true`, якщо є хоч один збіг, інакше `false`. diff --git a/9-regular-expressions/02-regexp-character-classes/article.md b/9-regular-expressions/02-regexp-character-classes/article.md index 34e3232e2..4e90277d3 100644 --- a/9-regular-expressions/02-regexp-character-classes/article.md +++ b/9-regular-expressions/02-regexp-character-classes/article.md @@ -18,9 +18,9 @@ let regexp = /\d/; alert( str.match(regexp) ); // 1 ``` -Без прапора `pattern:g` регулярний вираз шукає лише перший збіг, тобто першу цифру `pattern:\d`. +Без прапорця `pattern:g` регулярний вираз шукає лише перший збіг, тобто першу цифру `pattern:\d`. -Давайте додамо прапор `pattern:g`, щоб знайти всі цифри: +Давайте додамо прапорець `pattern:g`, щоб знайти всі цифри: ```js run let str = "+1(703)-123-45-67"; @@ -128,7 +128,7 @@ alert( "CS4".match(/CS.4/) ); // null, немає збігів тому що н ### Крапка, як буквально будь-який символ із прапорцем "s". -За замовчуванням крапка не відповідає символу нового рядка `\n`. +Типово крапка не відповідає символу нового рядка `\n`. Наприклад, регулярний вираз `pattern:A.B` відповідає `match:A`, а потім `match:B` з будь-яким символом між ними, крім символу нового рядка `\n`: @@ -138,14 +138,14 @@ alert( "A\nB".match(/A.B/) ); // null (немає збігів) Є багато ситуацій, коли ми хотіли б, щоб крапка означала буквально "будь-який символ", включаючи новий рядок. -Ось що робить прапор `pattern:s`. Якщо регулярний вираз містить його, то крапка `pattern:.` відповідає буквально будь-якому символу: +Ось що робить прапорець `pattern:s`. Якщо регулярний вираз містить його, то крапка `pattern:.` відповідає буквально будь-якому символу: ```js run alert( "A\nB".match(/A.B/s) ); // A\nB (збіг!) ``` ````warn header="Не підтримується в IE" -Прапор `pattern:s` не підтримується в IE. +Прапорець `pattern:s` не підтримується в IE. На щастя, є альтернатива, яка працює всюди. Ми можемо використовувати регулярний вираз, як-от `pattern:[\s\S]`, щоб знаходити "будь-який символ" (цей шаблон буде описано в статті ). @@ -191,10 +191,10 @@ alert( "1 - 5".match(/\d\s-\s\d/) ); // 1 - 5, також працює - `pattern:\d` -- цифри. - `pattern:\D` -- нецифри. - `pattern:\s` -- символи пробілів, табуляції, символи нового рядка. -- `pattern:\S` -- усі, крім `pattern:\s`. +- `pattern:\S` -- усі символи, крім `pattern:\s`. - `pattern:\w` -- латинські літери, цифри, підкреслення `'_'`. -- `pattern:\W` -- усі, крім `pattern:\w`. -- `pattern:.` -- будь-який символ, якщо з прапорцем регулярного виразу `'s'`, інакше будь-який, крім символу нового рядка `\n`. +- `pattern:\W` -- усі символи, крім `pattern:\w`. +- `pattern:.` -- будь-який символ, якщо використовується з прапорцем регулярного виразу `'s'`, інакше будь-який символ, крім символу нового рядка `\n`. ...Але це ще не все! diff --git a/9-regular-expressions/03-regexp-unicode/article.md b/9-regular-expressions/03-regexp-unicode/article.md index 0e3d2dcbc..16c1b5e6c 100644 --- a/9-regular-expressions/03-regexp-unicode/article.md +++ b/9-regular-expressions/03-regexp-unicode/article.md @@ -1,10 +1,10 @@ # Юнікод: прапорець "u" та клас \p{...} -У JavaScript для рядків використовується кодування [Юнікод](https://uk.wikipedia.org/wiki/Юнікод). Більшість символів кодуються 2 байтами, що дозволяє представити максимум 65536 символів. +У JavaScript для рядків використовується кодування [Юнікод](https://uk.wikipedia.org/wiki/Юнікод). Більшість символів кодуються 2-ма байтами, що дозволяє представити максимум 65536 символів. -Цей діапазон недостатньо великий для кодування всіх можливих символів, тому деякі рідкісні символи кодуються 4 байтами, наприклад `𝒳` (математичний X) або `😄` (смайл), деякі ієрогліфи тощо. +Цей діапазон недостатньо великий для кодування всіх можливих символів, тому деякі рідкісні символи кодуються 4-ма байтами, наприклад `𝒳` (математичний X) або `😄` (смайл), деякі ієрогліфи тощо. -Ось значення Юнікодів для деяких символів: +Ось Юнікод значення для деяких символів: | Символ | Юнікод | Кількість байтів у Юнікоді | |------------|---------|--------| @@ -25,11 +25,11 @@ alert('😄'.length); // 2 alert('𝒳'.length); // 2 ``` -...Але ми бачимо, що лише один, правда ж? Річ у тому, що властивість `length` трактує 4 байти, як два символи по 2 байти. Це не правильно, адже їх необхідно розглядати тільки разом (так звана "сурогатна пара", детальніше у розділі ). +...Але ми бачимо, що лише один, правда ж? Річ у тому, що властивість `length` трактує 4 байти, як два символи по 2 байти. Це неправильно, адже їх необхідно розглядати тільки разом (так звана "сурогатна пара", детальніше у розділі ). -За замовчуванням регулярні вирази також розглядають 4-байтові "довгі символи" як пару 2-байтових. Як і у випадку з рядками, це може призвести до дивних результатів. Ми побачимо це трохи пізніше, у розділі . +Типово регулярні вирази також розглядають 4-байтові "довгі символи" як пару 2-байтових. Як і у випадку з рядками, це може призвести до дивних результатів. Ми побачимо це трохи пізніше, у розділі . -На відміну від рядків, регулярні вирази мають прапорець `pattern:u`, який виправляє такі проблеми. З таким прапорцем регулярний вираз правильно обробляє 4-байтові символи. А також стає доступним пошук з використанням властивостей Юнікоду, який ми розглянемо далі. +На відміну від рядків, регулярні вирази мають прапорець `pattern:u`, який виправляє такі проблеми. З таким прапорцем регулярний вираз правильно обробляє 4-байтові символи. Ба більше, стає доступним пошук з використанням властивостей Юнікоду, який ми розглянемо далі. ## Властивості Юнікоду \p{...} @@ -41,7 +41,7 @@ alert('𝒳'.length); // 2 Наприклад, `\p{Letter}` позначає літеру будь-якою мовою. Ми також можемо використовувати коротший запис `\p{L}`, оскільки `L` є псевдонімом `Letter`. Майже для кожної властивості існують варіанти коротшого запису. -У наведеному нижче прикладі буде знайдено три види літер: англійська, грузинська та корейська. +У наведеному нижче прикладі ми будемо шукати три види літер: англійську, грузинську та корейську. ```js run let str = "A ბ ㄱ"; @@ -91,14 +91,14 @@ alert( str.match(/\p{L}/g) ); // null (немає збігів, \p не прац - сурогат `Cs`. -Наприклад, якщо нам потрібно знайти маленькі літери, ми можемо написати `pattern:\p{Ll}`, знаки пунктуації `pattern:\p{P}` і так далі. +Наприклад, якщо нам потрібно знайти маленькі літери, ми можемо написати `pattern:\p{Ll}`, знаки пунктуації `pattern:\p{P}` тощо. Існують також інші похідні категорії, наприклад: - `Alphabetic` (`Alpha`), містить в собі літери `L`, а також числа позначені за допомогою літер `Nl` (наприклад, Ⅻ - символ для римської цифри 12), і деякі інші символи `Other_Alphabetic` (`OAlpha`). - `Hex_Digit` містить шістнадцяткові числа: `0-9`, `a-f`. -- ...І так далі. +- ...тощо. -Юнікод підтримує велику кількість властивостей, і їхній повний перелік вимагав би дуже багато місця, тому ось посилання: +Юнікод підтримує велику кількість властивостей, і їхній повний перелік зайняв би дуже багато місця, тому ось посилання: - Перелік усіх властивостей за символом: . - Перелік усіх символів за властивістю: . @@ -107,7 +107,7 @@ alert( str.match(/\p{L}/g) ); // null (немає збігів, \p не прац ### Приклад: шістнадцяткові числа -Наприклад, пошукаймо шістнадцяткові числа, записані в форматі `xFF`, де замість `F` може бути будь-яка шістнадцяткова цифра (0..9 or A..F). +Наприклад, знайдемо шістнадцяткові числа, записані в форматі `xFF`, де замість `F` може бути будь-яка шістнадцяткова цифра (0..9 or A..F). Шістнадцяткову цифру можна позначити як `pattern:\p{Hex_Digit}`: @@ -119,11 +119,11 @@ alert("число: xAF".match(regexp)); // xAF ### Приклад: китайські ієрогліфи -Пошукаймо китайські ієрогліфи. +Знайдемо китайські ієрогліфи. Нам допоможе властивість Юнікоду -- `Script` (система письма), яка може мати значення: `Cyrillic`(Кирилиця), `Greek` (Грецька), `Arabic` (Арабська), `Han` (Китайська) та інші, [тут повний перелік](https://en.wikipedia.org/wiki/Script_(Unicode)). -Для пошуку символів у певній системі письма ми повинні використати `pattern:Script=`, наприклад для літер кирилиці: `pattern:\p{sc=Cyrillic}`, для китайських ієрогліфів: `pattern:\p{sc=Han}`, і так далі. +Для пошуку символів у певній системі письма ми повинні використовувати `pattern:Script=`, наприклад для літер кирилиці: `pattern:\p{sc=Cyrillic}`, для китайських ієрогліфів: `pattern:\p{sc=Han}` тощо. ```js run let regexp = /\p{sc=Han}/gu; // поверне китайські ієрогліфи @@ -137,7 +137,7 @@ alert( str.match(regexp) ); // 你,好 Символи, які позначають валюту, такі як `$`, `€`, `¥`, мають властивість `pattern:\p{Currency_Symbol}`, короткий псевдонім: `pattern:\p{Sc}`. -Використаємо його для пошуку цін у форматі «валюта, за якою йде цифра»: +Використаємо його для пошуку цін у форматі "валюта, за якою йде цифра": ```js run let regexp = /\p{Sc}\d/gu; diff --git a/9-regular-expressions/04-regexp-anchors/1-start-end/solution.md b/9-regular-expressions/04-regexp-anchors/1-start-end/solution.md index dcf38afb3..977f04679 100644 --- a/9-regular-expressions/04-regexp-anchors/1-start-end/solution.md +++ b/9-regular-expressions/04-regexp-anchors/1-start-end/solution.md @@ -1,5 +1,5 @@ Порожній рядок є єдиним збігом: він починається і негайно закінчується. -Задача ще раз доводить що якорі не являються символами, вони є тестами. +Задача ще раз доводить що якорі не є символами, вони є додатковими умовами. -Рядок порожній `""`. Механізм спочатку відповідає `pattern:^` (початок введення), так, він там, а потім одразу кінцевий `pattern:$`, він також є тут. Отже, збіг є. +Рядок порожній `""`. Рушій спочатку перевіряє `pattern:^` (початок введення), так, він там, а потім одразу кінцевий `pattern:$`, він також збігається. Отже, збіг є, рядок відповідає шаблону. diff --git a/9-regular-expressions/04-regexp-anchors/article.md b/9-regular-expressions/04-regexp-anchors/article.md index cf6445146..27506310a 100644 --- a/9-regular-expressions/04-regexp-anchors/article.md +++ b/9-regular-expressions/04-regexp-anchors/article.md @@ -1,8 +1,8 @@ -# Якорі: початок рядка ^ і кінець $ +# Якорі: початок ^ і кінець $ рядка -Символи каретки `pattern:^` і долара `pattern:$` мають особливе значення в регулярному виразі. Їх називають "якорі". +Символи каретки `pattern:^` і долара `pattern:$` мають особливе значення в регулярних виразах. Їх називають "якорі". -Каретка `pattern:^` збігається з початком тексту, а долар `pattern:$` з кінцем. +Каретка `pattern:^` змушує шукати збіг на початку тексту, а долар `pattern:$` в кінці. Наприклад, перевіримо, чи текст починається з `Марійка`: @@ -11,24 +11,24 @@ let str1 = "Марійка мала маленьке ягня"; alert( /^Марійка/.test(str1) ); // true ``` -Шаблон `pattern:^Марійка` означає: "початок рядка, а потім Марійка". +Шаблон `pattern:^Марійка` означає: "шукаємо Марійка на початку рядка". -Відповідно, ми можемо протестувати чи закінчується рядок з `сніг` використавши `pattern:сніг$` +Відповідно, ми можемо перевірити чи закінчується рядок на `сніг` використавши `pattern:сніг$` ```js run let str1 = "ця шерсть була білою як сніг"; alert( /сніг$/.test(str1) ); // true ``` -Конкретно в цих випадках ми можемо використати методи рядка `startsWith/endsWith`. Для складніших тестів слід використовувати регулярні вирази. +Звісно, в цих випадках ми можемо використати методи рядка `startsWith/endsWith`. Проте для складнішого пошуку слід використовувати регулярні вирази. ## Перевірка на повний збіг Обидва якорі разом `pattern:^...$` часто використовуються для перевірки того, чи рядок повністю відповідає шаблону. Наприклад, щоб перевірити, чи введені користувачем дані мають правильний формат. -Перевіримо, чи є рядок часом у форматі: `12:34`. Тобто: дві цифри, потім двокрапка, а потім ще дві цифри. +Перевіримо, чи представлено час у рядку в форматі: `12:34`. Тобто: дві цифри, потім двокрапка, а потім ще дві цифри. -У мові регулярних виразів це виглядає так `pattern:\d\d:\d\d`: +Мовою регулярних виразів це виглядає так `pattern:\d\d:\d\d`: ```js run let goodInput = "12:34"; @@ -39,14 +39,14 @@ alert( regexp.test(goodInput) ); // true alert( regexp.test(badInput) ); // false ``` -Тут збіг для `pattern:\d\d:\d\d` має починатися точно після початку тексту `pattern:^`, а кінцевий `pattern:$` має йти відразу в слід. +Тут збіг для `pattern:\d\d:\d\d` має починатися точно після початку тексту `pattern:^`, і не мати нічого зайвого в кінці `pattern:$`. -Весь рядок має бути саме в цьому форматі. Якщо є будь-яке відхилення або додатковий символ, результатом буде `false`. +Весь рядок має бути саме в цьому форматі. Якщо є будь-яке відхилення або додатковий символ, то `test` поверне `false`. -Якір поводиться інакше, якщо присутній прапорець `pattern:m`. Розглянемо це в наступній статті. +Якір поводиться інакше, якщо присутній прапорець `pattern:m`. Ми розглянемо це в наступній статті. ```smart header="У якорів \"нульова ширина\"" -Якорі `pattern:^` та `pattern:$` -- це перевірки. В них нульова ширина. +Якорі `pattern:^` та `pattern:$` -- це додаткові перевірки. В них нульова ширина. -Іншими словами, вони не додають до результату пошуку символи, а лише заставляють рушій регулярних виразів перевірити умову (початок/кінець тексту). +Іншими словами, вони не додають до результату пошуку символи, а лише змушують рушій регулярних виразів перевірити умову (початок/кінець тексту). ``` diff --git a/9-regular-expressions/05-regexp-multiline-mode/article.md b/9-regular-expressions/05-regexp-multiline-mode/article.md index 5b040a09b..c5d192393 100644 --- a/9-regular-expressions/05-regexp-multiline-mode/article.md +++ b/9-regular-expressions/05-regexp-multiline-mode/article.md @@ -1,6 +1,6 @@ -# Багаторядковий режим якорів ^ $, прапора "m" +# Багаторядковий режим якорів ^ $, прапорець "m" -Багаторядковий режим вмикається прапором `pattern:m`. +Багаторядковий режим вмикається прапорцем `pattern:m`. Це впливає лише на поведінку `pattern:^` і `pattern:$`. @@ -20,7 +20,7 @@ console.log( str.match(/^\d/gm) ); // 1, 2, 3 */!* ``` -Без прапора `pattern:m` збігається лише перша цифра: +Без прапорця `pattern:m` збігається лише перша цифра: ```js run let str = `1 місце: Вінні @@ -32,7 +32,7 @@ console.log( str.match(/^\d/g) ); // 1 */!* ``` -Це тому, що за замовчуванням карет `pattern:^` збігається лише на початку тексту, а в багаторядковому режимі -- на початку будь-якого рядка. +Типово шаблон `pattern:^` збігається лише на початку тексту, а в багаторядковому режимі -- на початку будь-якого рядка. ```smart "Початок рядка" формально означає "відразу після розриву рядка": тестовий `pattern:^` у багаторядковому режимі збігається в усіх позиціях, яким передує символ нового рядка `\n`. @@ -54,10 +54,10 @@ let str = `Вінні: 1 console.log( str.match(/\d$/gm) ); // 1,2,3 ``` -Без прапора `pattern:m`, символ долара `pattern:$` відповідатиме лише кінці всього тексту, тому буде знайдено лише останню цифру. +Без прапорця `pattern:m`, символ долара `pattern:$` буде шукати співпадіння лише в кінці всього тексту, тому буде знайдено лише останню цифру. ```smart -"Кінець рядка" формально означає "безпосередньо перед розривом рядка": тестовий `pattern:$` у багаторядковому режимі збігається в усіх позиціях після символу нового рядка `\n`. +"Кінець рядка" формально означає "безпосередньо перед розривом рядка": тестовий `pattern:$` у багаторядковому режимі збігається на усіх позиціях після символу нового рядка `\n`. І в кінці тексту. ``` @@ -78,10 +78,10 @@ let str = `Вінні: 1 console.log( str.match(/\d\n/g) ); // 1\n,2\n ``` -Як бачимо, 2 збіги замість 3-х. +Як бачимо, 2 збіги замість 3-ьох. -Це тому, що після `об'єкт:3` немає нового рядка (хоча є кінець тексту, тому він відповідає `pattern:$`). +Це тому, що після `subject:3` немає нового рядка (хоча є кінець тексту, тому він відповідає `pattern:$`). Ще одна відмінність: тепер кожен збіг містить символ нового рядка `match:\n`. На відміну від якорів `pattern:^` `pattern:$`, які лише перевіряють умову (початок/кінець рядка), `\n` є символом, тому він стає частиною результату. -Отже, `\n` у шаблоні використовується, коли нам потрібні символи нового рядка в результаті, тоді як якорі використовуються, щоб знайти щось на початку/кінці рядка. +Отже, `\n` у шаблоні використовується, коли нам потрібно включити символи нового рядка в збіг, тоді як якорі використовуються, лише щоб знайти щось на початку/кінці рядка. diff --git a/9-regular-expressions/06-regexp-boundary/1-find-time-hh-mm/task.md b/9-regular-expressions/06-regexp-boundary/1-find-time-hh-mm/task.md index 706210cdc..5ca23abc6 100644 --- a/9-regular-expressions/06-regexp-boundary/1-find-time-hh-mm/task.md +++ b/9-regular-expressions/06-regexp-boundary/1-find-time-hh-mm/task.md @@ -2,7 +2,7 @@ Час відповідає формату: `години:хвилини`. І години, і хвилини мають по дві цифри, наприклад, `09:00`. -Створіть регулярний вираз для пошуку часу у рядку : `subject:Сніданок о 09:00 в кімнаті 123:456.` +Напишіть регулярний вираз для пошуку часу у рядку : `subject:Сніданок о 09:00 в кімнаті 123:456.` P.S. У цьому випадку немає потреби перевіряти правильність часу, тому `25:99` також може бути правильним результатом пошуку. diff --git a/9-regular-expressions/06-regexp-boundary/article.md b/9-regular-expressions/06-regexp-boundary/article.md index 587cf2e9e..3783c85e5 100644 --- a/9-regular-expressions/06-regexp-boundary/article.md +++ b/9-regular-expressions/06-regexp-boundary/article.md @@ -2,15 +2,15 @@ Межа слова `pattern:\b` -- це така ж сама перевірка як і `pattern:^` та `pattern:$`. -Коли механізм регулярних виразів (програмний модуль, який здійснює пошук регулярних виразів) стикається з `pattern:\b`, він перевіряє, чи є позиція в рядку межею слова. +Коли рушій регулярних виразів (програмний модуль, який здійснює пошук регулярних виразів) стикається з `pattern:\b`, він перевіряє, чи є позиція в рядку межею слова. Є три різні позиції, які кваліфікуються як межі слова: -- На початку рядка, якщо його перший символ представляє собою буквенний символ `pattern:\w`. -- Між двома символами в рядку, де один є буквенним символом `pattern:\w`, а інший -- ні. -- В кінці рядка, якщо його останній символ представляє собою буквенний символ `pattern:\w`. +- На початку рядка, якщо його перший символ є буквеним символом `pattern:\w`. +- Між двома символами в рядку, де один є буквеним символом `pattern:\w`, а інший -- ні. +- В кінці рядка, якщо його останній символ представляє собою буквений символ `pattern:\w`. -Наприклад, регулярний вираз `pattern:\bJava\b` буде знайдено в `subject:Hello, Java!`, де `subject:Java` -- окреме слово, але не буде знайдено в `subject:Hello, JavaScript!`. +Наприклад, регулярний вираз `pattern:\bJava\b` знайде збіги в `subject:Hello, Java!`, де `subject:Java` -- окреме слово, але не в `subject:Hello, JavaScript!`. ```js run alert( "Hello, Java!".match(/\bJava\b/) ); // Java @@ -21,13 +21,13 @@ alert( "Hello, JavaScript!".match(/\bJava\b/) ); // null ![](hello-java-boundaries.svg) -Виходить, що воно відповідає шаблону `pattern:\bHello\b` за наступними критеріями: +Виходить, що рядок відповідає шаблону `pattern:\bHello\b` за наступними критеріями: -1. На початку рядка відповідає першій перевірці `pattern:\b`. +1. Початок рядка відповідає першій перевірці `pattern:\b`. 2. Потім відповідає цілому слову `pattern:Hello`. 3. І, врешті-решт, перевірка `pattern:\b` також збігається, оскільки ми знаходимось між символом `subject:o` і комою. -Отже, шаблон `pattern:\bHello\b` буде збігатися, при цьому, `pattern:\bHell\b` -- ні (оскільки немає закінчення слова після символу `l`), а також не буде збігатися `pattern:Java!\b` (оскільки знак оклику не буквенний символ `pattern:\w`, тому після нього немає й межі слова). +Отже, шаблон `pattern:\bHello\b` буде збігатися, при цьому, `pattern:\bHell\b` -- ні (оскільки немає закінчення слова після символу `l`), а також не буде збігатися `pattern:Java!\b` (оскільки знак оклику не буквений символ `pattern:\w`, тому після нього немає й межі слова). ```js run alert( "Hello, Java!".match(/\bHello\b/) ); // Hello @@ -46,7 +46,7 @@ alert( "12,34,56".match(/\b\d\d\b/g) ); // 12,34,56 ``` ```warn header="Межа слова `pattern:\b` не працює з алфавітами, відмінними від латинського" -Перевірка межі слова `pattern:\b` звіряє чи є `pattern:\w` з однієї сторони і "не `pattern:\w`" - з іншої. +Перевірка межі слова `pattern:\b` звіряє чи є `pattern:\w` з однієї сторони і "не `pattern:\w`" -- з іншої. Але `pattern:\w` позначає латинську літеру `a-z` (або цифру чи нижнє підкреслення), тому перевірка не працює для інших символів, наприклад, кирилиці чи ієрогліфів. ``` diff --git a/9-regular-expressions/07-regexp-escaping/article.md b/9-regular-expressions/07-regexp-escaping/article.md index c8a5cd96c..e10903bf4 100644 --- a/9-regular-expressions/07-regexp-escaping/article.md +++ b/9-regular-expressions/07-regexp-escaping/article.md @@ -13,7 +13,7 @@ Щоб використовувати спеціальний символ як звичайний, додайте перед ним бекслеш: `pattern:\.`. -Це також називається "екранування символу". +Це називається "екранування символу". Наприклад: ```js run @@ -96,4 +96,4 @@ alert( "Chapter 5.1".match(regexp) ); // 5.1 - Для пошуку спеціальних символів `pattern:[ \ ^ $ . | ? * + ( )`, нам потрібно додати перед ними `\` ("екранувати їх"). - Нам також потрібно екранувати `/`, якщо ми знаходимося всередині `pattern:/.../` (але не всередині `new RegExp`). -- При передачі рядка в `new RegExp`, нам необхідно подвоїти бекслеши `\\`, тому що лапки рядка поглинають один з них. +- При передачі рядка в `new RegExp`, нам необхідно подвоїти бекслеши `\\`, бо лапки рядка поглинають один з них. diff --git a/9-regular-expressions/08-regexp-character-sets-and-ranges/1-find-range-1/task.md b/9-regular-expressions/08-regexp-character-sets-and-ranges/1-find-range-1/task.md index 88d4d9781..bd5f7db3a 100644 --- a/9-regular-expressions/08-regexp-character-sets-and-ranges/1-find-range-1/task.md +++ b/9-regular-expressions/08-regexp-character-sets-and-ranges/1-find-range-1/task.md @@ -2,4 +2,4 @@ У нас є регулярний вираз `pattern:/Java[^script]/`. -Чи знайде він співпадіння у рядку `subject:Java`? А у рядку `subject:JavaScript`? +Чи знайде він співпадіння у рядку `subject:Java`? А у `subject:JavaScript`? diff --git a/9-regular-expressions/08-regexp-character-sets-and-ranges/article.md b/9-regular-expressions/08-regexp-character-sets-and-ranges/article.md index eecff114f..b0ba014c0 100644 --- a/9-regular-expressions/08-regexp-character-sets-and-ranges/article.md +++ b/9-regular-expressions/08-regexp-character-sets-and-ranges/article.md @@ -19,7 +19,7 @@ alert( "Mop top".match(/[tm]op/gi) ); // "Mop", "top" ```js run // знайти "V", потім [o чи i], потім "la" -alert( "Voila".match(/V[oi]la/) ); // null, no matches +alert( "Voila".match(/V[oi]la/) ); // null, співпадінь не знайдено ``` Шаблон шукає: @@ -36,28 +36,28 @@ alert( "Voila".match(/V[oi]la/) ); // null, no matches До прикладу, `pattern:[a-z]` шукатиме символу в діапазоні від `a` до `z`, а `pattern:[0-5]` дорівнює цифрам в діапазоні від `0` до `5`. -В нижченаведеному прикладі ми шукатимемо літеру `"x"` за якою слідують дві цифри, або літери від `A` до `F`: +В нижченаведеному прикладі ми шукатимемо літеру `"x"` за якою ідуть дві цифри, або літери від `A` до `F`: ```js run alert( "Exception 0xAF".match(/x[0-9A-F][0-9A-F]/g) ); // xAF ``` -Тут `pattern:[0-9A-F]` має в собі одразу два діапазони: він шукає символ, який є або цифрою від `0` до `9` , або літерою від `A` до `F`. +Тут `pattern:[0-9A-F]` має в собі одразу два діапазони: він шукає символ, який є або цифрою від `0` до `9`, або літерою від `A` до `F`. Якби ми захотіли шукати літери не тільки верхнього, а й нижнього регістру, ми могли б додати діапазон `a-f`: `pattern:[0-9A-Fa-f]`. Або додати флаг `pattern:i`. Крім того, всередині `[…]` ми можемо використовувати символьні класи. -До прикладу, якщо ми захочемо знайти символ "слова" `pattern:\w` , або дефіс `pattern:-`, набір виглядатиме наступним чином `pattern:[\w-]`. +До прикладу, якщо ми захочемо знайти символ "слова" `pattern:\w` , або дефіс `pattern:-`, набір виглядатиме наступним чином `pattern:[\w-]`. Комбінувати декілька класів теж можливо, наприклад `pattern:[\s\d]` означає "пробіл, або цифра". ```smart header="Символьні класи це лише скорочення для деяких наборів символів" До прикладу: -- **\d** -- це те саме, що й `pattern:[0-9]`, -- **\w** -- це те саме, що й `pattern:[a-zA-Z0-9_]`, -- **\s** -- це те саме, що й `pattern:[\t\n\v\f\r ]`, плюс декілька інших рідкісних пробільних символів Unicode. +- **\d** -- те саме, що й `pattern:[0-9]`, +- **\w** -- те саме, що й `pattern:[a-zA-Z0-9_]`, +- **\s** -- те саме, що й `pattern:[\t\n\v\f\r ]`, плюс декілька інших рідкісних пробільних символів Unicode. ``` ### Приклад: \w в інших мовах світу @@ -71,7 +71,7 @@ alert( "Exception 0xAF".match(/x[0-9A-F][0-9A-F]/g) ); // xAF - `Alphabetic` (`Alpha`) - для літер, - `Mark` (`M`) - для акцентів, - `Decimal_Number` (`Nd`) - для цифр, -- `Connector_Punctuation` (`Pc`) - для нижнього підкреслення `'_'` і тому подібних символів, +- `Connector_Punctuation` (`Pc`) - для нижнього підкреслення `'_'` і подібних символів, - `Join_Control` (`Join_C`) - два спеціальних коди `200c` та `200d`, які використовуються у лігатурах, зокрема в арабській мові. Шаблон в дії: @@ -90,7 +90,7 @@ alert( str.match(regexp) ); // H,i,你,好,1,2 ```warn header="Internet Explorer не підтримує Unicode властивості" Unicode властивості `pattern:p{…}` недоступні у Internet Explorer. Втім, якщо вони нам все ж потрібні, ми можемо скористатись бібліотекою [XRegExp](https://xregexp.com/). -або просто вказати діапазон потрібних нам символів певною мовою, наприклад `pattern:[а-я]` для літер кирилицею. +Або просто вказати діапазон потрібних нам символів з необхідної мови, наприклад `pattern:[а-я]` для літер кирилицею. ``` ## Діапазони виключень diff --git a/9-regular-expressions/17-regexp-methods/article.md b/9-regular-expressions/17-regexp-methods/article.md index 2c0498516..ee41a4512 100644 --- a/9-regular-expressions/17-regexp-methods/article.md +++ b/9-regular-expressions/17-regexp-methods/article.md @@ -8,7 +8,7 @@ Він має 3 режими: -1. Якщо `regexp` не має прапору `pattern:g`, тоді він повертає перший збіг у вигляді масиву з групами захоплення та властивостями `index` (позиція збігу), `input` (введений рядок, дорівнює `str`): +1. Якщо `regexp` не має прапорця `pattern:g`, тоді він повертає перший збіг у вигляді масиву з групами захоплення та властивостями `index` (позиція збігу), `input` (введений рядок, дорівнює `str`): ```js run let str = "Я люблю JavaScript"; @@ -24,7 +24,7 @@ alert( result.input ); // Я люблю JavaScript (вихідний рядок) ``` -2. Якщо `regexp` має прапор `pattern:g`, тоді він повертає масив всіх збігів у вигляді рядків, без груп захоплення та інших деталей. +2. Якщо `regexp` має прапорець `pattern:g`, тоді він повертає масив всіх збігів у вигляді рядків, без груп захоплення та інших деталей. ```js run let str = "Я люблю JavaScript"; @@ -34,9 +34,9 @@ alert( result.length ); // 1 ``` -3. Якщо збігів нема, повертається `null`, незалежно від наявності прапору `pattern:g`. +3. Якщо збігів немає, повертається `null`, незалежно від наявності прапорця `pattern:g`. - Це важливий нюанс. Якщо збігів нема, ми отримаємо не порожній масив, а `null`. Легко помилитись, забувши про це: + Це важливий нюанс. Якщо збігів немає, ми отримаємо не порожній масив, а `null`. Легко помилитись, забувши про це: ```js run let str = "Я люблю JavaScript"; @@ -57,15 +57,15 @@ [recent browser="new"] -Метод `str.matchAll(regexp)` - це "новіший, покращений" варіант `str.match`. +Метод `str.matchAll(regexp)` -- це новіший і покращений варіант `str.match`. В основному, його використовують для пошуку всіх збігів з усіма групами. Існує 3 відмінності від `match`: -1. Він повертає ітерований об’єкт із збігами замість масиву. Ми можемо отримати з нього звичайний масив за допомогою `Array.from`. -2. Кожен збіг повертається у вигляді масиву з групами захоплення (той самий формат, що й `str.match` без прапору `pattern:g`). -3. Якщо результатів нема, метод повертає порожній ітерований об’єкт замість `null`. +1. Він повертає ітерований об’єкт зі збігами замість масиву. Ми можемо отримати з нього звичайний масив за допомогою `Array.from`. +2. Кожен збіг повертається у вигляді масиву з групами захоплення (той самий формат, що й `str.match` без прапорця `pattern:g`). +3. Якщо результатів немає, метод повертає порожній ітерований об’єкт замість `null`. Приклад використання: @@ -75,7 +75,7 @@ let regexp = /<(.*?)>/g; let matchAll = str.matchAll(regexp); -alert(matchAll); // [object RegExp String Iterator], не масив, але ітерований +alert(matchAll); // [object RegExp String Iterator], не масив а обʼєкт, проте ітерований matchAll = Array.from(matchAll); // тепер масив @@ -86,7 +86,7 @@ alert( firstMatch.index ); // 0 alert( firstMatch.input ); //

Вітаю, світе!

``` -Якщо ми використаємо `for..of` для циклічного проходження збігами `matchAll`, тоді ми більше не потребуємо `Array.from`. +Якщо ми використовуємо цикл `for..of` для проходження збігами `matchAll`, то в `Array.from` немає потреби. ## str.split(regexp|substr, limit) @@ -95,13 +95,13 @@ alert( firstMatch.input ); //

Вітаю, світе!

Можна використовувати `split` з рядками, як-то: ```js run -alert('12-34-56'.split('-')) // array of ['12', '34', '56'] +alert('12-34-56'.split('-')) // масив ['12', '34', '56'] ``` Але ми так само можемо ділити за допомогою регулярного виразу: ```js run -alert('12, 34, 56'.split(/,\s*/)) // array of ['12', '34', '56'] +alert('12, 34, 56'.split(/,\s*/)) // масив ['12', '34', '56'] ``` ## str.search(regexp) @@ -109,7 +109,7 @@ alert('12, 34, 56'.split(/,\s*/)) // array of ['12', '34', '56'] Метод `str.search(regexp)` повертає позицію першого збігу або `-1`, якщо нічого не знайдено: ```js run -let str = "Чорнил краплина – мільйонів думок причина"; +let str = "A drop of ink may make a million think"; alert( str.search( /ink/i ) ); // 8 (позиція першого збігу) ``` @@ -120,12 +120,12 @@ alert( str.search( /ink/i ) ); // 8 (позиція першого збігу) ## str.replace(str|regexp, str|func) -Це загальний метод для пошуку та заміни, один з найбільш корисних. «Швейцарський ніж» подібних операцій. +Це загальний метод для пошуку та заміни, один з найбільш корисних. "Швейцарський ніж" подібних операцій. Ми можемо користуватись ним без регулярних виразів, шукаючи та замінюючи підрядок: ```js run -// заміна дефіс на двокрапку +// заміна дефісу на двокрапку alert('12-34-56'.replace("-", ":")) // 12:34-56 ``` @@ -135,7 +135,7 @@ alert('12-34-56'.replace("-", ":")) // 12:34-56 Ви можете побачити це в попередньому прикладі: лише перше `"-"` замінюється на `":"`. -Аби знайти всі дефіси, нам потрібно використати не рядок `"-"`, а регулярний вираз `pattern:/-/g`, з обов’язковим прапором `pattern:g`: +Аби знайти всі дефіси, нам потрібно використати не рядок `"-"`, а регулярний вираз `pattern:/-/g`, з обов’язковим прапорцем `pattern:g`: ```js run // заміна всіх дефісів на двокрапку @@ -156,10 +156,10 @@ alert( '12-34-56'.replace( *!*/-/g*/!*, ":" ) ) // 12:34:56 Для прикладу: ```js run -let str = "Іван Сірко"; +let str = "John Smith"; // переставляє місцями ім’я та прізвище -alert(str.replace(/(іван) (сірко)/i, '$2, $1')) // Сірко, Іван +alert(str.replace(/(john) (smith)/i, '$2, $1')) // Smith, John ``` **Для ситуацій, які потребують "розумної" перестановки, другий аргумент може бути функцією.** @@ -174,9 +174,9 @@ alert(str.replace(/(іван) (сірко)/i, '$2, $1')) // Сірко, Іван 4. `input` -- вихідний рядок, 5. `groups` -- об’єкт з іменованими групами. -Якщо в регулярному виразі нема дужок, тоді є лише 3 аргументи: `func(str, offset, input)`. +Якщо в регулярному виразі немає дужок, тоді є лише 3 аргументи: `func(str, offset, input)`. -Наприклад, приведемо всі збіги до верхнього регістру: +Наприклад, переведемо всі збіги у верхній регістр: ```js run let str = "html та css"; @@ -195,11 +195,11 @@ alert("Хо-хо-хо".replace(/хо/gi, (match, offset) => offset)); // 0-3-6 В прикладі нижче, наявні дві дужки, тож функція заміни матиме 5 аргументів: перший є повним збігом, далі 2 дужки, після цього (не використані в прикладі) позиція збігу та вихідний рядок: ```js run -let str = "Іван Сірко"; +let str = "John Smith"; let result = str.replace(/(\p{L}+) (\p{L}+)/u, (match, name, surname) => `${surname}, ${name}`); -alert(result); // Сірко, Іван +alert(result); // Smith, John ``` Для пошуку літери, які написані кирилицею, слід увімкнути режим Unicode (`/u` в кінці виразу) та використовувати спеціальні властивості Юнікоду (`\p{L}`) для пошуку літер. Ці властивості ми розглядали в розділі . @@ -208,17 +208,17 @@ alert(result); // Сірко, Іван Якщо груп багато, зручно використовувати залишкові параметри для доступу до них: ```js run -let str = "Іван Сірко"; +let str = "John Smith"; let result = str.replace(/(\p{L}+) (\p{L}+)/u, (...match) => `${match[2]}, ${match[1]}`); -alert(result); // Сірко, Іван +alert(result); // Smith, John ``` В іншому випадку, якщо ми використовуємо іменовані групи, тоді об’єкт `groups` завжди йде останнім після них, тож ми можемо отримати його наступним чином: ```js run -let str = "Іван Сірко"; +let str = "John Smith"; let result = str.replace(/(?\p{L}+) (?\p{L}+)/u, (...match) => { let groups = match.pop(); @@ -226,19 +226,19 @@ let result = str.replace(/(?\p{L}+) (?\p{L}+)/u, (...match) => { return `${groups.surname}, ${groups.name}`; }); -alert(result); // Сірко, Іван +alert(result); // Smith, John ``` -Використання функції максимально розкриває можливості заміни, тому що ми отримуємо всю інформацію про збіг, доступ до зовнішніх змінних та можемо робити все, що потрібно. +Використання функції максимально розкриває можливості заміни, тому що ми отримуємо всю інформацію про збіг, доступ до зовнішніх змінних та можемо робити все, що нам потрібно. ## str.replaceAll(str|regexp, str|func) -Цей метод, по суті, такий самий, що й `str.replace`, з двома значними відмінностями: +Цей метод, по суті, такий самий, як і `str.replace`, але з двома значними відмінностями: -1. Якщо перший аргумент є рядком, він замінює *всі входження* в рядку, тоді як `replace` замінює лише *перше входження*. -2. Якщо перший аргумент є регулярним виразом без прапору `g`, виникне помилка. З прапором `g`, метод працюватиме аналогічно до `replace`. +1. Якщо перший аргумент є рядком, він замінює *всі збіги* в рядку, тоді як `replace` замінює лише *перший збіг*. +2. Якщо перший аргумент є регулярним виразом без прапорця `g`, виникне помилка. З прапороцем `g`, метод працюватиме аналогічно до `replace`. -Основний випадок використання `replaceAll` -- заміна всіх входжень збігу в рядку. +Основний випадок використання `replaceAll` -- заміна всіх збігів в рядку. Наприклад: @@ -252,9 +252,9 @@ alert('12-34-56'.replaceAll("-", ":")) // 12:34:56 Метод `regexp.exec(str)` повертає збіг для `regexp` в рядку `str`. На відміну від попередніх методів, він застосовується до регулярного виразу, а не рядку. -Його поведінка залежить від наявності в регулярному виразі прапору `pattern:g`. +Його поведінка залежить від наявності в регулярному виразі прапорця `pattern:g`. -Якщо нема прапору `pattern:g`, тоді `regexp.exec(str)` повертає перший збіг у вигляді `str.match(regexp)`. Ця поведінка не додає нічого нового. +Якщо немає прапорця `pattern:g`, тоді `regexp.exec(str)` повертає перший збіг у вигляді `str.match(regexp)`. Ця поведінка не додає нічого нового. Але за наявності `pattern:g`: - Виклик `regexp.exec(str)` повертає перший збіг та зберігає позицію після нього всередині властивості `regexp.lastIndex`. @@ -267,7 +267,7 @@ alert('12-34-56'.replaceAll("-", ":")) // 12:34:56 В минулому, коли метод `str.matchAll` ще не був доданий в JavaScript, виклики `regexp.exec` використовувались в циклі для отримання всіх збігів, разом з групами: ```js run -let str = 'Детальніше про JavaScript тут https://javascript.info'; +let str = 'More about JavaScript at https://javascript.info'; let regexp = /javascript/ig; let result; @@ -286,20 +286,20 @@ while (result = regexp.exec(str)) { Для прикладу: ```js run -let str = 'Вітаю, світе!'; +let str = 'Hello, world!'; -let regexp = /\w+/g; // без прапору "g", властивість lastIndex ігнорується +let regexp = /\w+/g; // без прапорця "g", властивість lastIndex ігнорується regexp.lastIndex = 5; // пошук з п’ятої позиції (з коми) -alert( regexp.exec(str) ); // світе +alert( regexp.exec(str) ); // world ``` -Якщо регулярний вираз має прапор `pattern:y`, тоді пошук проводитиметься абсолютно чітко з позиції `regexp.lastIndex`. +Якщо регулярний вираз має прапорець `pattern:y`, тоді пошук відбудеться з позиції `regexp.lastIndex`. -У прикладі зверху, замінимо прапор `pattern:g` на `pattern:y`. Збігів не буде, бо на 5 позиції нема слова: +У прикладі зверху, замінимо прапорець `pattern:g` на `pattern:y`. Збігів не буде, бо на 5 позиції немає слова: ```js run -let str = 'Вітаю, світе!'; +let str = 'Hello, world!'; let regexp = /\w+/y; regexp.lastIndex = 5; // пошук саме з 5 позиції @@ -332,18 +332,18 @@ alert( *!*/люблю/i*/!*.test(str) ); // false alert( str.search(*!*/люблю/i*/!*) != -1 ); // false ``` -Якщо регулярний вираз має прапор `pattern:g`, тоді `regexp.test` проводить пошук, починаючи з `regexp.lastIndex` та оновлює цю властивість, аналогічно до `regexp.exec`. +Якщо регулярний вираз має прапорець `pattern:g`, тоді `regexp.test` проводить пошук, починаючи з `regexp.lastIndex` та оновлює цю властивість, аналогічно до `regexp.exec`. Тож ми можемо використовувати його для пошуку з визначеної позиції: ```js run -let regexp = /люблю/gi; +let regexp = /love/gi; -let str = "Я люблю JavaScript"; +let str = "I love JavaScript"; // починаємо пошук з позиції 10: regexp.lastIndex = 10; -alert( regexp.test(str) ); // false (збігу нема) +alert( regexp.test(str) ); // false (збігу немає) ``` ````warn header="Один і той самий глобальний регулярний вираз, протестований багато разів на різних даних, може помилятись" @@ -360,5 +360,5 @@ alert( regexp.test("javascript") ); // false Проблема саме в `regexp.lastIndex`, що не є нульовим під час виконання другого тесту. -Оминути це можна, встановлюючи `regexp.lastIndex = 0` перед кожним пошуком. Іншим рішенням є використання методів рядків `str.match/search/...` замість методів регулярних виразів, так як вони не використовують `lastIndex`. +Оминути це можна, встановлюючи `regexp.lastIndex = 0` перед кожним пошуком. Іншим рішенням є використання методів рядків `str.match/search/...` замість методів регулярних виразів, бо вони не використовують `lastIndex`. ````