Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Вичитка розділу "Регулярні вирази" #621

Merged
merged 11 commits into from
Jan 13, 2025
60 changes: 30 additions & 30 deletions 9-regular-expressions/01-regexp-introduction/article.md
Original file line number Diff line number Diff line change
@@ -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 про те, що це регулярний вираз. Вони відіграють таку саму роль, як і лапки для позначення рядків.
Expand All @@ -29,25 +29,25 @@ regexp = /шаблон/gmi; // з прапорами g,m та i (будуть о

Основна різниця між цими двома синтаксами полягає в тому, що слеши `/.../` не допускають жодних вставок змінних (на зразок тих, що прописуються через `${...}`). Вони повністю статичні.

Слеши використовуються, коли ми на момент написання коду точно знаємо, яким буде регулярний вираз - і це більшість ситуацій. А `new RegExp` - коли ми хочемо створити регулярний вираз "на льоту" з динамічно згенерованого рядка, наприклад:
Слеши використовуються, коли ми на момент написання коду точно знаємо, яким буде регулярний вираз -- і це більшість ситуацій. А `new RegExp` -- коли ми хочемо створити регулярний вираз "на льоту" з динамічно згенерованого рядка, наприклад:

```js
let tag = prompt("Який тег ви хочете знайти?", "h2");

let regexp = new RegExp(`<${tag}>`); // те саме, що /<h2>/ при відповіді "h2" на запит вище
```

## Прапори
## Прапорці

Регулярні вирази можуть мати прапори, які впливають на пошук.
Регулярні вирази можуть мати прапорці, які впливають на пошук.

У JavaScript їх всього шість:

`pattern:i`
: З цим прапором пошук не залежить від регістру: немає різниці між `A` та `a` (див. приклад нижче).
: З цим прапорцем пошук не залежить від регістру: немає різниці між `A` та `a` (див. приклад нижче).

`pattern:g`
: З цим прапором пошук шукає всі збіги, без нього - лише перше.
: З цим прапорцем пошук шукає всі збіги, без нього -- лише перший.

`pattern:m`
: Багаторядковий режим (розглядається в розділі <info:regexp-multiline-mode>).
Expand All @@ -56,39 +56,39 @@ let regexp = new RegExp(`<${tag}>`); // те саме, що /<h2>/ при від
: Вмикає режим "dotall", при якому крапка `pattern:.` може відповідати символу нового рядка `\n` (розглядається у розділі <info:regexp-character-classes>).

`pattern:u`
: Вмикає повну підтримку Юнікоду. Прапор дозволяє коректну обробку сурогатних пар (докладніше про це у розділі <info:regexp-unicode>).
: Вмикає повну підтримку Юнікоду. Цей прапорець дозволяє коректну обробку сурогатних пар (докладніше про це у розділі <info:regexp-unicode>).

`pattern:y`
: Режим пошуку на конкретній позиції в тексті (описаний у розділі <info:regexp-sticky>)

```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
Expand All @@ -99,7 +99,7 @@ let regexp = new RegExp(`<${tag}>`); // те саме, що /<h2>/ при від
```
У цьому масиві можуть бути інші індекси, крім `0`, якщо частина регулярного виразу виділена в дужки. Ми розберемо це у розділі <info:regexp-groups>.

3. І, нарешті, якщо збігів немає, то, незалежно від наявності прапора `pattern:g`, повертається `null`.
3. І, нарешті, якщо збігів немає, то, незалежно від наявності прапорця `pattern:g`, повертається `null`.

Це дуже важливий аспект. За відсутності збігів повертається не порожній масив, а саме `null`. Якщо про це забути, можна легко припуститися помилки, наприклад:

Expand All @@ -121,16 +121,16 @@ let regexp = new RegExp(`<${tag}>`); // те саме, що /<h2>/ при від

## Заміна: 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` ми можемо використовувати спеціальні комбінації символів для вставки фрагментів збігу:
Expand All @@ -140,7 +140,7 @@ alert( "Ми будемо, ми будемо".replace(/ми/ig, "Я") ); // Я
|`$&`|вставляє всі знайдені збіги|
|<code>$&#096;</code>|вставляє частину рядка до збігу|
|`$'`|вставляє частину рядка після збігу|
|`$n`|якщо `n` це 1-2 значне число, вставляє вміст n-ї скобочної групи регулярного виразу, більше у розділі <info:regexp-groups>|
|`$n`|якщо `n` це 1-2 значне число, вставляє вміст n-ої скобочної групи регулярного виразу, більше у розділі <info:regexp-groups>|
|`$<name>`|вставляє вміст скобочної групи з ім'ям `name`, також вивчимо у розділі <info:regexp-groups>|
|`$$`|вставляє символ `"$"` |

Expand All @@ -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`.
16 changes: 8 additions & 8 deletions 9-regular-expressions/02-regexp-character-classes/article.md
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -128,7 +128,7 @@ alert( "CS4".match(/CS.4/) ); // null, немає збігів тому що н

### Крапка, як буквально будь-який символ із прапорцем "s".

За замовчуванням крапка не відповідає символу нового рядка `\n`.
Типово крапка не відповідає символу нового рядка `\n`.

Наприклад, регулярний вираз `pattern:A.B` відповідає `match:A`, а потім `match:B` з будь-яким символом між ними, крім символу нового рядка `\n`:

Expand All @@ -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]`, щоб знаходити "будь-який символ" (цей шаблон буде описано в статті <info:regexp-character-sets-and-ranges>).

Expand Down Expand Up @@ -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`.

...Але це ще не все!

Expand Down
Loading