From 763042b93bbedd4e4fbeaa457a31a0efd2a9013d Mon Sep 17 00:00:00 2001 From: SamGreenberg Date: Wed, 11 Jan 2023 22:42:25 +0300 Subject: [PATCH 1/2] Capturing groups --- .../11-regexp-groups/01-test-mac/solution.md | 16 +- .../11-regexp-groups/01-test-mac/task.md | 18 +- .../02-find-webcolor-3-or-6/solution.md | 12 +- .../02-find-webcolor-3-or-6/task.md | 10 +- .../03-find-decimal-numbers/solution.md | 4 +- .../03-find-decimal-numbers/task.md | 8 +- .../04-parse-expression/solution.md | 44 ++-- .../04-parse-expression/task.md | 18 +- .../11-regexp-groups/article.md | 240 +++++++++--------- 9 files changed, 185 insertions(+), 185 deletions(-) diff --git a/9-regular-expressions/11-regexp-groups/01-test-mac/solution.md b/9-regular-expressions/11-regexp-groups/01-test-mac/solution.md index f7a5f1e39..acc3bf5b5 100644 --- a/9-regular-expressions/11-regexp-groups/01-test-mac/solution.md +++ b/9-regular-expressions/11-regexp-groups/01-test-mac/solution.md @@ -1,21 +1,21 @@ -A two-digit hex number is `pattern:[0-9a-f]{2}` (assuming the flag `pattern:i` is set). +Двоцифрове шістнадцяткове число можна записати як `pattern:[0-9a-f]{2}`(припустивши, що задано прапор `pattern:i`). -We need that number `NN`, and then `:NN` repeated 5 times (more numbers); +Нам потрібно число `NN`, а за ним `:NN`, повторене 5 разів (більше чисел); -The regexp is: `pattern:[0-9a-f]{2}(:[0-9a-f]{2}){5}` +Регулярний вираз: `pattern:[0-9a-f]{2}(:[0-9a-f]{2}){5}` -Now let's show that the match should capture all the text: start at the beginning and end at the end. That's done by wrapping the pattern in `pattern:^...$`. +Тепер продемонструємо, що збіг має захоплювати весь текст: з самого початку до самого кінця. Робиться це через огортання патерну в `pattern:^...$`. -Finally: +В підсумку: ```js run let regexp = /^[0-9a-f]{2}(:[0-9a-f]{2}){5}$/i; alert( regexp.test('01:32:54:67:89:AB') ); // true -alert( regexp.test('0132546789AB') ); // false (no colons) +alert( regexp.test('0132546789AB') ); // false (без двокрапок) -alert( regexp.test('01:32:54:67:89') ); // false (5 numbers, need 6) +alert( regexp.test('01:32:54:67:89') ); // false (5 чисел, має бути 6) -alert( regexp.test('01:32:54:67:89:ZZ') ) // false (ZZ in the end) +alert( regexp.test('01:32:54:67:89:ZZ') ) // false (ZZ в кінці) ``` diff --git a/9-regular-expressions/11-regexp-groups/01-test-mac/task.md b/9-regular-expressions/11-regexp-groups/01-test-mac/task.md index a2e799cfa..6d6a6ca4b 100644 --- a/9-regular-expressions/11-regexp-groups/01-test-mac/task.md +++ b/9-regular-expressions/11-regexp-groups/01-test-mac/task.md @@ -1,20 +1,20 @@ -# Check MAC-address +# Перевірити MAC-адресу -[MAC-address](https://en.wikipedia.org/wiki/MAC_address) of a network interface consists of 6 two-digit hex numbers separated by a colon. +[MAC-адреса](https://en.wikipedia.org/wiki/MAC_address) мережевого інтерфейсу складається з 6 двоцифрових чисел шістнадцяткової системи, розділених двокрапкою. -For instance: `subject:'01:32:54:67:89:AB'`. +Наприклад: `subject:'01:32:54:67:89:AB'`. -Write a regexp that checks whether a string is MAC-address. +Напишіть регулярний вираз, який перевіряє, чи є рядок MAC-адресою. -Usage: +Приклад використання: ```js -let regexp = /your regexp/; +let regexp = /ваш регулярний вираз/; alert( regexp.test('01:32:54:67:89:AB') ); // true -alert( regexp.test('0132546789AB') ); // false (no colons) +alert( regexp.test('0132546789AB') ); // false (без двокрапок) -alert( regexp.test('01:32:54:67:89') ); // false (5 numbers, must be 6) +alert( regexp.test('01:32:54:67:89') ); // false (5 чисел, має бути 6) -alert( regexp.test('01:32:54:67:89:ZZ') ) // false (ZZ at the end) +alert( regexp.test('01:32:54:67:89:ZZ') ) // false (ZZ в кінці) ``` diff --git a/9-regular-expressions/11-regexp-groups/02-find-webcolor-3-or-6/solution.md b/9-regular-expressions/11-regexp-groups/02-find-webcolor-3-or-6/solution.md index 0806dc4fd..ab4e55b95 100644 --- a/9-regular-expressions/11-regexp-groups/02-find-webcolor-3-or-6/solution.md +++ b/9-regular-expressions/11-regexp-groups/02-find-webcolor-3-or-6/solution.md @@ -1,12 +1,12 @@ -A regexp to search 3-digit color `#abc`: `pattern:/#[a-f0-9]{3}/i`. +Регулярний вираз для пошуку тризначного коду кольору `#abc`: `pattern:/#[a-f0-9]{3}/i`. -We can add exactly 3 more optional hex digits. We don't need more or less. The color has either 3 or 6 digits. +Ми можемо додати рівно 3 додаткові шістнадцяткові цифри, не більше й не менше. Колір містить 3 або 6 цифр. -Let's use the quantifier `pattern:{1,2}` for that: we'll have `pattern:/#([a-f0-9]{3}){1,2}/i`. +Використаємо для цього квантифікатор `pattern:{1,2}`: отримаємо `pattern:/#([a-f0-9]{3}){1,2}/i`. -Here the pattern `pattern:[a-f0-9]{3}` is enclosed in parentheses to apply the quantifier `pattern:{1,2}`. +В цьому випадку, патерн `pattern:[a-f0-9]{3}` оточений дужками для застосування квантифікатора `pattern:{1,2}`. -In action: +На прикладі: ```js run let regexp = /#([a-f0-9]{3}){1,2}/gi; @@ -16,7 +16,7 @@ let str = "color: #3f3; background-color: #AA00ef; and: #abcd"; alert( str.match(regexp) ); // #3f3 #AA00ef #abc ``` -There's a minor problem here: the pattern found `match:#abc` in `subject:#abcd`. To prevent that we can add `pattern:\b` to the end: +Бачимо невелику проблему: патерн знайшов `match:#abc` в `subject:#abcd`. Для запобігання цьому, додамо в кінці `pattern:\b`: ```js run let regexp = /#([a-f0-9]{3}){1,2}\b/gi; diff --git a/9-regular-expressions/11-regexp-groups/02-find-webcolor-3-or-6/task.md b/9-regular-expressions/11-regexp-groups/02-find-webcolor-3-or-6/task.md index 09108484a..603144933 100644 --- a/9-regular-expressions/11-regexp-groups/02-find-webcolor-3-or-6/task.md +++ b/9-regular-expressions/11-regexp-groups/02-find-webcolor-3-or-6/task.md @@ -1,14 +1,14 @@ -# Find color in the format #abc or #abcdef +# Знайти колір у форматі #abc або #abcdef -Write a RegExp that matches colors in the format `#abc` or `#abcdef`. That is: `#` followed by 3 or 6 hexadecimal digits. +Напишіть регулярний вираз, що знаходить збіг по кольорам у форматі `#abc` або `#abcdef`. Формула є наступною: `#`, за яким знаходяться 3 або 6 шістнадцяткових цифр. -Usage example: +Приклад використання: ```js -let regexp = /your regexp/g; +let regexp = /ваш регулярний вираз/g; let str = "color: #3f3; background-color: #AA00ef; and: #abcd"; alert( str.match(regexp) ); // #3f3 #AA00ef ``` -P.S. This should be exactly 3 or 6 hex digits. Values with 4 digits, such as `#abcd`, should not match. +P.S. Має бути саме 3 або 6 шістнадцяткових цифр. Значення з 4 цифрами, такі як `#abcd`, не мають рахуватись за збіг. diff --git a/9-regular-expressions/11-regexp-groups/03-find-decimal-numbers/solution.md b/9-regular-expressions/11-regexp-groups/03-find-decimal-numbers/solution.md index 813d619ef..4abbbd407 100644 --- a/9-regular-expressions/11-regexp-groups/03-find-decimal-numbers/solution.md +++ b/9-regular-expressions/11-regexp-groups/03-find-decimal-numbers/solution.md @@ -1,6 +1,6 @@ -A positive number with an optional decimal part is: `pattern:\d+(\.\d+)?`. +Додатне число з необов’язковою десятковою частиною: `pattern:\d+(\.\d+)?`. -Let's add the optional `pattern:-` in the beginning: +Додамо необов’язковий `pattern:-` на початку: ```js run let regexp = /-?\d+(\.\d+)?/g; diff --git a/9-regular-expressions/11-regexp-groups/03-find-decimal-numbers/task.md b/9-regular-expressions/11-regexp-groups/03-find-decimal-numbers/task.md index 4f5a73fff..e5744ca44 100644 --- a/9-regular-expressions/11-regexp-groups/03-find-decimal-numbers/task.md +++ b/9-regular-expressions/11-regexp-groups/03-find-decimal-numbers/task.md @@ -1,11 +1,11 @@ -# Find all numbers +# Знайти всі числа -Write a regexp that looks for all decimal numbers including integer ones, with the floating point and negative ones. +Напишіть регулярний вираз, який шукатиме всі десяткові числа, включно з числами цілими, з плаваючою комою та від’ємними. -An example of use: +Приклад використання: ```js -let regexp = /your regexp/g; +let regexp = /ваш регулярний вираз/g; let str = "-1.5 0 2 -123.4."; diff --git a/9-regular-expressions/11-regexp-groups/04-parse-expression/solution.md b/9-regular-expressions/11-regexp-groups/04-parse-expression/solution.md index ac67519bb..a86ad8b76 100644 --- a/9-regular-expressions/11-regexp-groups/04-parse-expression/solution.md +++ b/9-regular-expressions/11-regexp-groups/04-parse-expression/solution.md @@ -1,21 +1,21 @@ -A regexp for a number is: `pattern:-?\d+(\.\d+)?`. We created it in the previous task. +Регулярний вираз для числа є наступним: `pattern:-?\d+(\.\d+)?`. Його ми створили в рамках попередньої задачі. -An operator is `pattern:[-+*/]`. The hyphen `pattern:-` goes first in the square brackets, because in the middle it would mean a character range, while we just want a character `-`. +Оператором слугуватиме `pattern:[-+*/]`. Дефіс `pattern:-` стоїть першим в квадратних дужках, бо позиція посередині означає діапазон знаків, тоді як нам потрібен лише `-`. -The slash `/` should be escaped inside a JavaScript regexp `pattern:/.../`, we'll do that later. +Варто уникати символу `/` всередині регулярного виразу JavaScript `pattern:/.../`, зробимо це потім. -We need a number, an operator, and then another number. And optional spaces between them. +Нам потрібне число, оператор, тоді ще одне число. Та можливі пробіли між ними. -The full regular expression: `pattern:-?\d+(\.\d+)?\s*[-+*/]\s*-?\d+(\.\d+)?`. +Повний регулярний вираз: `pattern:-?\d+(\.\d+)?\s*[-+*/]\s*-?\d+(\.\d+)?`. -It has 3 parts, with `pattern:\s*` between them: -1. `pattern:-?\d+(\.\d+)?` - the first number, -1. `pattern:[-+*/]` - the operator, -1. `pattern:-?\d+(\.\d+)?` - the second number. +Він містить 3 частини, з `pattern:\s*` між ними: +1. `pattern:-?\d+(\.\d+)?` - перше число, +1. `pattern:[-+*/]` - оператор, +1. `pattern:-?\d+(\.\d+)?` - друге число. -To make each of these parts a separate element of the result array, let's enclose them in parentheses: `pattern:(-?\d+(\.\d+)?)\s*([-+*/])\s*(-?\d+(\.\d+)?)`. +Аби зробити кожну з цих частин окремим елементом масиву результатів, помістимо їх в круглі дужки: `pattern:(-?\d+(\.\d+)?)\s*([-+*/])\s*(-?\d+(\.\d+)?)`. -In action: +На прикладі: ```js run let regexp = /(-?\d+(\.\d+)?)\s*([-+*\/])\s*(-?\d+(\.\d+)?)/; @@ -23,22 +23,22 @@ let regexp = /(-?\d+(\.\d+)?)\s*([-+*\/])\s*(-?\d+(\.\d+)?)/; alert( "1.2 + 12".match(regexp) ); ``` -The result includes: +Вміст результату: -- `result[0] == "1.2 + 12"` (full match) -- `result[1] == "1.2"` (first group `(-?\d+(\.\d+)?)` -- the first number, including the decimal part) -- `result[2] == ".2"` (second group`(\.\d+)?` -- the first decimal part) -- `result[3] == "+"` (third group `([-+*\/])` -- the operator) -- `result[4] == "12"` (forth group `(-?\d+(\.\d+)?)` -- the second number) -- `result[5] == undefined` (fifth group `(\.\d+)?` -- the last decimal part is absent, so it's undefined) +- `result[0] == "1.2 + 12"` (повний збіг) +- `result[1] == "1.2"` (перша група `(-?\d+(\.\d+)?)` -- перше число, включаючи десяткову частину) +- `result[2] == ".2"` (друга група `(\.\d+)?` -- перша десяткова частина) +- `result[3] == "+"` (третя група `([-+*\/])` -- оператор) +- `result[4] == "12"` (четверта група `(-?\d+(\.\d+)?)` -- друге число) +- `result[5] == undefined` (п’ята група `(\.\d+)?` -- остання десяткова частина відсутня, тому вона undefined) -We only want the numbers and the operator, without the full match or the decimal parts, so let's "clean" the result a bit. +Нам потрібні лише числа та оператор, без повного збігу чи десяткових частин, тож проведемо невелику "чистку" результату. -The full match (the arrays first item) can be removed by shifting the array `result.shift()`. +Повний збіг (перший елемент масиву) можна прибрати методом масиву `result.shift()`. -Groups that contain decimal parts (number 2 and 4) `pattern:(.\d+)` can be excluded by adding `pattern:?:` to the beginning: `pattern:(?:\.\d+)?`. +Групи 2 та 5, що містять десяткові частини `pattern:(.\d+)`, можна оминути, додавши `pattern:?:` на початку: `pattern:(?:\.\d+)?`. -The final solution: +Кінцевий варіант: ```js run function parse(expr) { diff --git a/9-regular-expressions/11-regexp-groups/04-parse-expression/task.md b/9-regular-expressions/11-regexp-groups/04-parse-expression/task.md index 8b54d4683..eb8476db9 100644 --- a/9-regular-expressions/11-regexp-groups/04-parse-expression/task.md +++ b/9-regular-expressions/11-regexp-groups/04-parse-expression/task.md @@ -1,23 +1,23 @@ -# Parse an expression +# Парсинг виразу -An arithmetical expression consists of 2 numbers and an operator between them, for instance: +Арифметичний вираз складається з двох чисел та оператору між ними, наприклад: - `1 + 2` - `1.2 * 3.4` - `-3 / -6` - `-2 - 2` -The operator is one of: `"+"`, `"-"`, `"*"` or `"/"`. +Оператором може бути: `"+"`, `"-"`, `"*"` або `"/"`. -There may be extra spaces at the beginning, at the end or between the parts. +Додаткові пробіли можуть бути на початку, в кінці чи всередині виразу. -Create a function `parse(expr)` that takes an expression and returns an array of 3 items: +Напишіть функцію `parse(expr)`, яка приймає вираз та повертає масив з 3 елементів: -1. The first number. -2. The operator. -3. The second number. +1. Перше число. +2. Оператор. +3. Друге число. -For example: +Наприклад: ```js let [a, op, b] = parse("1.2 * 3.4"); diff --git a/9-regular-expressions/11-regexp-groups/article.md b/9-regular-expressions/11-regexp-groups/article.md index 796e23f54..d3a4aad19 100644 --- a/9-regular-expressions/11-regexp-groups/article.md +++ b/9-regular-expressions/11-regexp-groups/article.md @@ -1,31 +1,31 @@ -# Capturing groups +# Групи захоплення -A part of a pattern can be enclosed in parentheses `pattern:(...)`. This is called a "capturing group". +Частину патерну можна поставити в круглі дужки `pattern:(...)`. Це називається "група захоплення". -That has two effects: +Такий прийом має два наслідки: -1. It allows to get a part of the match as a separate item in the result array. -2. If we put a quantifier after the parentheses, it applies to the parentheses as a whole. +1. Він дозволяє отримати частину збігу в якості окремого елементу в масиві результатів. +2. Якщо ми поставимо квантифікатор після дужок, він застосується до всього вмісту дужок. -## Examples +## Приклади -Let's see how parentheses work in examples. +Розглянемо як працюють круглі дужки на прикладах. -### Example: gogogo +### Приклад: gogogo -Without parentheses, the pattern `pattern:go+` means `subject:g` character, followed by `subject:o` repeated one or more times. For instance, `match:goooo` or `match:gooooooooo`. +Без круглих дужок, патерн `pattern:go+` означає символ `subject:g`, за яким слідує `subject:o` на повторі один чи кілька разів. Тобто, `match:goooo` чи `match:gooooooooo`. -Parentheses group characters together, so `pattern:(go)+` means `match:go`, `match:gogo`, `match:gogogo` and so on. +Круглі дужки об’єднують символи в групи, тож `pattern:(go)+` значить `match:go`, `match:gogo`, `match:gogogo` і так далі. ```js run alert( 'Gogogo now!'.match(/(go)+/ig) ); // "Gogogo" ``` -### Example: domain +### Приклад: домен -Let's make something more complex -- a regular expression to search for a website domain. +Зробимо дещо складніше – регулярний вираз для пошуку домену сайту. -For example: +Наприклад: ``` mail.com @@ -33,9 +33,9 @@ users.mail.com smith.users.mail.com ``` -As we can see, a domain consists of repeated words, a dot after each one except the last one. +Як бачимо, домен складається з повторюваних слів та крапки після кожного з них(окрім останнього). -In regular expressions that's `pattern:(\w+\.)+\w+`: +В регулярних виразах це `pattern:(\w+\.)+\w+`: ```js run let regexp = /(\w+\.)+\w+/g; @@ -43,17 +43,17 @@ let regexp = /(\w+\.)+\w+/g; alert( "site.com my.site.com".match(regexp) ); // site.com,my.site.com ``` -The search works, but the pattern can't match a domain with a hyphen, e.g. `my-site.com`, because the hyphen does not belong to class `pattern:\w`. +Пошук працює, але патерн не збігатиметься з доменом з дефісом: наприклад, `my-site.com`, бо дефіс не належить до класу `pattern:\w`. -We can fix it by replacing `pattern:\w` with `pattern:[\w-]` in every word except the last one: `pattern:([\w-]+\.)+\w+`. +Ми можемо виправити це, замінивши `pattern:\w` на `pattern:[\w-]` в кожному слові(окрім останнього): `pattern:([\w-]+\.)+\w+`. -### Example: email +### Приклад: email -The previous example can be extended. We can create a regular expression for emails based on it. +Минулий приклад можна розширити. Спираючись на нього, ми можемо створити регулярний вираз для адрес електронної пошти. -The email format is: `name@domain`. Any word can be the name, hyphens and dots are allowed. In regular expressions that's `pattern:[-.\w]+`. +Формат електронної пошти: `name@domain`. Name може бути будь-яким словом, дефіси та крапки допускаються. В регулярних виразах це `pattern:[-.\w]+`. -The pattern: +Патерн є наступним: ```js run let regexp = /[-.\w]+@([\w-]+\.)+[\w-]+/g; @@ -61,27 +61,27 @@ let regexp = /[-.\w]+@([\w-]+\.)+[\w-]+/g; alert("my@mail.com @ his@site.com.uk".match(regexp)); // my@mail.com, his@site.com.uk ``` -That regexp is not perfect, but mostly works and helps to fix accidental mistypes. The only truly reliable check for an email can only be done by sending a letter. +Це неідеальний регулярний вираз, але здебільшого робочий та здатний виправити випадкові помилки. Єдина справді надійна перевірка електронної пошти – відправити листа. -## Parentheses contents in the match +## Вміст дужок всередині збігу -Parentheses are numbered from left to right. The search engine memorizes the content matched by each of them and allows to get it in the result. +Дужки нумеруються зліва направо. Пошукова система запам’ятовує вміст збігу для кожної з них та дозволяє отримати його всередині результату. -The method `str.match(regexp)`, if `regexp` has no flag `g`, looks for the first match and returns it as an array: +У випадку, якщо `regexp` не містить прапору `g`, метод `str.match(regexp)` шукає перший збіг та повертає його в якості масиву: -1. At index `0`: the full match. -2. At index `1`: the contents of the first parentheses. -3. At index `2`: the contents of the second parentheses. -4. ...and so on... +1. Індекс `0`: повний збіг. +2. Індекс `1`: вміст перших дужок. +3. Індекс `2`: вміст других дужок. +4. ...і так далі... -For instance, we'd like to find HTML tags `pattern:<.*?>`, and process them. It would be convenient to have tag content (what's inside the angles), in a separate variable. +Для прикладу, ми б хотіли знайти HTML теги `pattern:<.*?>` та обробити їх. Було б зручно мати вміст тегу (все, що всередині кутових дужок) в окремій змінній. -Let's wrap the inner content into parentheses, like this: `pattern:<(.*?)>`. +Огорнемо внутрішній вміст у круглі дужки, ось так: `pattern:<(.*?)>`. -Now we'll get both the tag as a whole `match:

` and its contents `match:h1` in the resulting array: +Тепер ми отримаємо як тег в цілому(`match:

`), так і його вміст(`match:h1`) в отриманому масиві: ```js run -let str = '

Hello, world!

'; +let str = '

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

'; let tag = str.match(/<(.*?)>/); @@ -89,23 +89,23 @@ alert( tag[0] ); //

alert( tag[1] ); // h1 ``` -### Nested groups +### Вкладені групи -Parentheses can be nested. In this case the numbering also goes from left to right. +Дужки можуть бути вкладеними. В нашому випадку, нумерація також проводиться зліва направо. -For instance, when searching a tag in `subject:` we may be interested in: +Наприклад, під час пошуку тегу в `subject:`, ми можемо бути зацікавленими в: -1. The tag content as a whole: `match:span class="my"`. -2. The tag name: `match:span`. -3. The tag attributes: `match:class="my"`. +1. Вміст тегу загалом: `match:span class="my"`. +2. Імені тегу: `match:span`. +3. Атрибутах тегу: `match:class="my"`. -Let's add parentheses for them: `pattern:<(([a-z]+)\s*([^>]*))>`. +Додамо до них дужки: `pattern:<(([a-z]+)\s*([^>]*))>`. -Here's how they are numbered (left to right, by the opening paren): +Ось як вони нумеруються (зліва направо, за відкриваючою дужкою): ![](regexp-nested-groups-pattern.svg) -In action: +На практиці: ```js run let str = ''; @@ -119,59 +119,59 @@ alert(result[2]); // span alert(result[3]); // class="my" ``` -The zero index of `result` always holds the full match. +Повний збіг завжди представлений в нульовому індексі `result`. -Then groups, numbered from left to right by an opening paren. The first group is returned as `result[1]`. Here it encloses the whole tag content. +Далі йдуть групи, нумеровані зліва направо за відкриваючою дужкою. Перша група розміщена в `result[1]`. В даному випадку, вона охоплює весь вміст тегу. -Then in `result[2]` goes the group from the second opening paren `pattern:([a-z]+)` - tag name, then in `result[3]` the tag: `pattern:([^>]*)`. +Далі, в `result[2]` отримуємо групу з других дужок `pattern:([a-z]+)` - ім’я тегу, в `result[3]` - тег `pattern:([^>]*)`. -The contents of every group in the string: +Вміст кожної групи в рядку: ![](regexp-nested-groups-matches.svg) -### Optional groups +### Необов’язкові групи -Even if a group is optional and doesn't exist in the match (e.g. has the quantifier `pattern:(...)?`), the corresponding `result` array item is present and equals `undefined`. +Навіть якщо група необов’язкова та не існує всередині збігу (тобто має квантифікатор `pattern:(...)?`), відповідний елемент масиву `result` наявний та дорівнює `undefined`. -For instance, let's consider the regexp `pattern:a(z)?(c)?`. It looks for `"a"` optionally followed by `"z"` optionally followed by `"c"`. +Для прикладу, розглянемо регулярний вираз `pattern:a(z)?(c)?`. Він шукає `"a"`, після якої може йти `"z"`, після якої може йти `"c"`. -If we run it on the string with a single letter `subject:a`, then the result is: +Якщо використати цей вираз для рядку з єдиною літерою `subject:a`, тоді результатом буде: ```js run let match = 'a'.match(/a(z)?(c)?/); alert( match.length ); // 3 -alert( match[0] ); // a (whole match) +alert( match[0] ); // a (повний збіг) alert( match[1] ); // undefined alert( match[2] ); // undefined ``` -The array has the length of `3`, but all groups are empty. +Довжина масиву дорівнює `3`, але всі групи порожні. -And here's a more complex match for the string `subject:ac`: +Ось приклад більш комплексного збігу для рядку `subject:ac`: ```js run let match = 'ac'.match(/a(z)?(c)?/) alert( match.length ); // 3 -alert( match[0] ); // ac (whole match) -alert( match[1] ); // undefined, because there's nothing for (z)? +alert( match[0] ); // ac (повний збіг) +alert( match[1] ); // undefined, бо для (z)? нічого не знайшлось alert( match[2] ); // c ``` -The array length is permanent: `3`. But there's nothing for the group `pattern:(z)?`, so the result is `["ac", undefined, "c"]`. +Довжина масиву є незмінною: `3`. Але для групи `pattern:(z)?` нічого не знайшлось, тому в результаті отримуємо `["ac", undefined, "c"]`. -## Searching for all matches with groups: matchAll +## Пошук усіх збігів з групами: matchAll -```warn header="`matchAll` is a new method, polyfill may be needed" -The method `matchAll` is not supported in old browsers. +```warn header="`matchAll` є новим методом, може знадобитись поліфіл" +Метод `matchAll` не підтримується старими браузерами. -A polyfill may be required, such as . +Поліфіл може бути обов’язковим, такий як . ``` -When we search for all matches (flag `pattern:g`), the `match` method does not return contents for groups. +Коли ми шукаємо всі збіги (прапор `pattern:g`), метод `match` не повертає вміст для груп. -For example, let's find all tags in a string: +Для прикладу, знайдемо всі теги в рядку: ```js run let str = '

'; @@ -181,55 +181,55 @@ let tags = str.match(/<(.*?)>/g); alert( tags ); //

,

``` -The result is an array of matches, but without details about each of them. But in practice we usually need contents of capturing groups in the result. +Як результат отримуємо масив збігів, але без індивідуальних деталей. На практиці ж ми зазвичай потребуємо вміст груп захоплення. -To get them, we should search using the method `str.matchAll(regexp)`. +Аби їх отримати, ми маємо здійснювати пошук методом `str.matchAll(regexp)`. -It was added to JavaScript language long after `match`, as its "new and improved version". +Його додали в JavaScript набагато пізніше за `match` в якості "нової та покращеної версії". -Just like `match`, it looks for matches, but there are 3 differences: +Як і `match`, метод шукає збіги, але з урахуванням 3 відмінностей: -1. It returns not an array, but an iterable object. -2. When the flag `pattern:g` is present, it returns every match as an array with groups. -3. If there are no matches, it returns not `null`, but an empty iterable object. +1. Він повертає не масив, а ітерований об’єкт. +2. За наявності прапору `pattern:g`, він повертає кожен збіг у вигляді масиву з групами. +3. Якщо збігів нема, він повертає замість `null` порожній ітерований об’єкт. -For instance: +Наприклад: ```js run let results = '

'.matchAll(/<(.*?)>/gi); -// results - is not an array, but an iterable object +// results – є не масивом, а ітерованим об’єктом alert(results); // [object RegExp String Iterator] alert(results[0]); // undefined (*) -results = Array.from(results); // let's turn it into array +results = Array.from(results); // перетворимо його на масив -alert(results[0]); //

,h1 (1st tag) -alert(results[1]); //

,h2 (2nd tag) +alert(results[0]); //

,h1 (перший тег) +alert(results[1]); //

,h2 (другий тег) ``` -As we can see, the first difference is very important, as demonstrated in the line `(*)`. We can't get the match as `results[0]`, because that object isn't pseudoarray. We can turn it into a real `Array` using `Array.from`. There are more details about pseudoarrays and iterables in the article . +Як можемо бачити, перша відмінність дуже важлива, як демонструється в рядку `(*)`. Ми не можемо отримати збіг у вигляді `results[0]`, бо цей об’єкт не є псевдомасивом. Ми можемо перетворити його на реальний `Array`, використовуючи `Array.from`. Детальніше про псевдомасиви та ітеровані об’єкти в статті . -There's no need in `Array.from` if we're looping over results: +Нема потреби в `Array.from`, якщо ми циклічно проходимось по результатам: ```js run let results = '

'.matchAll(/<(.*?)>/gi); for(let result of results) { alert(result); - // first alert:

,h1 - // second:

,h2 + // перший alert:

,h1 + // другий:

,h2 } ``` -...Or using destructuring: +...Або використовуємо деструктурування: ```js let [tag1, tag2] = '

'.matchAll(/<(.*?)>/gi); ``` -Every match, returned by `matchAll`, has the same format as returned by `match` without flag `pattern:g`: it's an array with additional properties `index` (match index in the string) and `input` (source string): +Кожен збіг, повернутий `matchAll`, форматується аналогічно до результату функції `match` без прапору `pattern:g`: масив з додатковими властивостями `index` (позиція збігу в рядку) та `input` (вихідний рядок): ```js run let results = '

'.matchAll(/<(.*?)>/gi); @@ -242,23 +242,23 @@ alert( tag1.index ); // 0 alert( tag1.input ); //

``` -```smart header="Why is a result of `matchAll` an iterable object, not an array?" -Why is the method designed like that? The reason is simple - for the optimization. +```smart header="Чому результатом `matchAll` є ітерований об’єкт, а не масив?" +Чому цей метод так спроектовано? Причина проста – заради оптимізації. -The call to `matchAll` does not perform the search. Instead, it returns an iterable object, without the results initially. The search is performed each time we iterate over it, e.g. in the loop. +Виклик `matchAll` не проводить пошуку. Натомість, повертається ітерований об’єкт, спочатку без результатів. Пошук проводиться кожного разу ми проходимось об’єктом, наприклад, всередині циклу. -So, there will be found as many results as needed, not more. +Тобто, буде знайдено потрібну кількість результатів, не більше. -E.g. there are potentially 100 matches in the text, but in a `for..of` loop we found 5 of them, then decided it's enough and made a `break`. Then the engine won't spend time finding other 95 matches. +Наведемо приклад: потенційно, в тексті існує 100 збігів, але всередині циклу `for..of` ми знайшли 5, тоді вирішили, що цього достатньо, та викликали `break`. Тоді система не витрачатиме час на пошук 95 інших збігів. ``` -## Named groups +## Іменовані групи -Remembering groups by their numbers is hard. For simple patterns it's doable, but for more complex ones counting parentheses is inconvenient. We have a much better option: give names to parentheses. +Пам’ятати групи за номерами важко. З простими патернами впоратись можна, але з підвищенням рівня комплексності рахувати дужки стає незручно. Існує кращий варіант: дати імена круглим дужкам. -That's done by putting `pattern:?` immediately after the opening paren. +Робиться це за допомогою `pattern:?` одразу після відкриваючої дужки. -For example, let's look for a date in the format "year-month-day": +На прикладі нижче, пошукаємо дату в форматі "year-month-day": ```js run *!* @@ -273,11 +273,11 @@ alert(groups.month); // 04 alert(groups.day); // 30 ``` -As you can see, the groups reside in the `.groups` property of the match. +Як ви можете бачити, групи розташовані всередині властивості збігу `.groups`. -To look for all dates, we can add flag `pattern:g`. +Аби зробити пошук по всіх датах, ми можемо додати прапор `pattern:g`. -We'll also need `matchAll` to obtain full matches, together with groups: +Нам також знадобиться `matchAll` для отримання повних збігів, разом з групами: ```js run let dateRegexp = /(?[0-9]{4})-(?[0-9]{2})-(?[0-9]{2})/g; @@ -290,27 +290,27 @@ for(let result of results) { let {year, month, day} = result.groups; alert(`${day}.${month}.${year}`); - // first alert: 30.10.2019 - // second: 01.01.2020 + // перший alert: 30.10.2019 + // другий: 01.01.2020 } ``` -## Capturing groups in replacement +## Групи захоплення для заміни -Method `str.replace(regexp, replacement)` that replaces all matches with `regexp` in `str` allows to use parentheses contents in the `replacement` string. That's done using `pattern:$n`, where `pattern:n` is the group number. +Метод `str.replace(regexp, replacement)` замінює всі збіги з `regexp` всередині `str` дозволяє користуватись вмістом дужок в рядку `replacement`. Це зроблено за допомогою `pattern:$n`, де `pattern:n` - номер групи. -For example, +Наприклад, ```js run -let str = "John Bull"; +let str = "Іван Зубр"; let regexp = /(\w+) (\w+)/; -alert( str.replace(regexp, '$2, $1') ); // Bull, John +alert( str.replace(regexp, '$2, $1') ); // Зубр, Іван ``` -For named parentheses the reference will be `pattern:$`. +Посилання на іменовані дужки можливе через `pattern:$`. -For example, let's reformat dates from "year-month-day" to "day.month.year": +Наприклад, реформатуємо дати з "year-month-day" на "day.month.year": ```js run let regexp = /(?[0-9]{4})-(?[0-9]{2})-(?[0-9]{2})/g; @@ -321,44 +321,44 @@ alert( str.replace(regexp, '$.$.$') ); // 30.10.2019, 01.01.2020 ``` -## Non-capturing groups with ?: +## Групи без захоплення з ?: -Sometimes we need parentheses to correctly apply a quantifier, but we don't want their contents in results. +Іноді ми потребуємо дужки для коректного застосування квантифікатора, але не хочемо бачити їх вміст в результатах. -A group may be excluded by adding `pattern:?:` in the beginning. +Групу можна виключити, додавши на початку `pattern:?:`. -For instance, if we want to find `pattern:(go)+`, but don't want the parentheses contents (`go`) as a separate array item, we can write: `pattern:(?:go)+`. +Для прикладу, якщо ми хочемо знайти `pattern:(go)+`, але не потребуємо вміст дужок (`go`) окремим елементом масиву, ми можемо написати: `pattern:(?:go)+`. -In the example below we only get the name `match:John` as a separate member of the match: +В прикладі нижче, ми отримуємо лише ім’я `match:Іван` окремим елементом збігу: ```js run -let str = "Gogogo John!"; +let str = "Gogogo Іван!"; *!* -// ?: excludes 'go' from capturing +// ?: захоплення не включає в себе 'go' let regexp = /(?:go)+ (\w+)/i; */!* let result = str.match(regexp); -alert( result[0] ); // Gogogo John (full match) -alert( result[1] ); // John -alert( result.length ); // 2 (no more items in the array) +alert( result[0] ); // Gogogo Іван (повний збіг) +alert( result[1] ); // Іван +alert( result.length ); // 2 (інших елементів у масиві нема) ``` -## Summary +## Підсумки -Parentheses group together a part of the regular expression, so that the quantifier applies to it as a whole. +Круглі дужки об’єднують в групу частину регулярного виразу, аби повноцінно застосувати до неї квантифікатор. -Parentheses groups are numbered left-to-right, and can optionally be named with `(?...)`. +Групи дужок нумеруються зліва направо та за бажанням можуть бути іменовані за допомогою `(?...)`. -The content, matched by a group, can be obtained in the results: +Вміст, що збігається з групою, може бути отриманий в результатах: -- The method `str.match` returns capturing groups only without flag `pattern:g`. -- The method `str.matchAll` always returns capturing groups. +- Метод `str.match` повертає групи захоплення лише без прапору `pattern:g`. +- Метод `str.matchAll` завжди повертає групи захоплення. -If the parentheses have no name, then their contents is available in the match array by its number. Named parentheses are also available in the property `groups`. +Якщо в дужок нема імені, їх вміст доступний в масиві збігу за їх номером. Іменовані дужки також доступні через властивість `groups`. -We can also use parentheses contents in the replacement string in `str.replace`: by the number `$n` or the name `$`. +Ми також можемо використовувати вміст дужок в рядку для заміни в `str.replace`: за номером `$n` або ім’ям `$`. -A group may be excluded from numbering by adding `pattern:?:` in its start. That's used when we need to apply a quantifier to the whole group, but don't want it as a separate item in the results array. We also can't reference such parentheses in the replacement string. +Групу можна виключити з нумерації, додавши `pattern:?:` на її початку. Цей прийом використовується за необхідності застосувати квантифікатор до всієї групи, але без появи окремого елементу в масиві результатів. Також, ми не можемо посилатись на такі дужки в рядку для заміни. From 00907f2a718fd9017b07b2583bee2ba19823a004 Mon Sep 17 00:00:00 2001 From: Stanislav Date: Sat, 25 Mar 2023 13:56:25 +0200 Subject: [PATCH 2/2] Apply suggestions from code review --- .../11-regexp-groups/01-test-mac/solution.md | 4 +- .../11-regexp-groups/01-test-mac/task.md | 2 +- .../02-find-webcolor-3-or-6/solution.md | 6 +- .../04-parse-expression/solution.md | 6 +- .../04-parse-expression/task.md | 4 +- .../11-regexp-groups/article.md | 70 +++++++++---------- 6 files changed, 46 insertions(+), 46 deletions(-) diff --git a/9-regular-expressions/11-regexp-groups/01-test-mac/solution.md b/9-regular-expressions/11-regexp-groups/01-test-mac/solution.md index acc3bf5b5..c85b604a8 100644 --- a/9-regular-expressions/11-regexp-groups/01-test-mac/solution.md +++ b/9-regular-expressions/11-regexp-groups/01-test-mac/solution.md @@ -1,10 +1,10 @@ -Двоцифрове шістнадцяткове число можна записати як `pattern:[0-9a-f]{2}`(припустивши, що задано прапор `pattern:i`). +Двоцифрове шістнадцяткове число можна записати як `pattern:[0-9a-f]{2}`(припустивши, що задано прапорець `pattern:i`). Нам потрібно число `NN`, а за ним `:NN`, повторене 5 разів (більше чисел); Регулярний вираз: `pattern:[0-9a-f]{2}(:[0-9a-f]{2}){5}` -Тепер продемонструємо, що збіг має захоплювати весь текст: з самого початку до самого кінця. Робиться це через огортання патерну в `pattern:^...$`. +Тепер продемонструємо, що збіг має захоплювати весь текст: з самого початку до самого кінця. Робиться це через огортання виразу в `pattern:^...$`. В підсумку: diff --git a/9-regular-expressions/11-regexp-groups/01-test-mac/task.md b/9-regular-expressions/11-regexp-groups/01-test-mac/task.md index 6d6a6ca4b..ebfa82c04 100644 --- a/9-regular-expressions/11-regexp-groups/01-test-mac/task.md +++ b/9-regular-expressions/11-regexp-groups/01-test-mac/task.md @@ -1,6 +1,6 @@ # Перевірити MAC-адресу -[MAC-адреса](https://en.wikipedia.org/wiki/MAC_address) мережевого інтерфейсу складається з 6 двоцифрових чисел шістнадцяткової системи, розділених двокрапкою. +[MAC-адреса](https://uk.wikipedia.org/wiki/MAC-адреса) мережевого інтерфейсу складається з 6 двоцифрових шістнадцяткових чисел, розділених двокрапкою. Наприклад: `subject:'01:32:54:67:89:AB'`. diff --git a/9-regular-expressions/11-regexp-groups/02-find-webcolor-3-or-6/solution.md b/9-regular-expressions/11-regexp-groups/02-find-webcolor-3-or-6/solution.md index ab4e55b95..122146510 100644 --- a/9-regular-expressions/11-regexp-groups/02-find-webcolor-3-or-6/solution.md +++ b/9-regular-expressions/11-regexp-groups/02-find-webcolor-3-or-6/solution.md @@ -4,9 +4,9 @@ Використаємо для цього квантифікатор `pattern:{1,2}`: отримаємо `pattern:/#([a-f0-9]{3}){1,2}/i`. -В цьому випадку, патерн `pattern:[a-f0-9]{3}` оточений дужками для застосування квантифікатора `pattern:{1,2}`. +В цьому випадку, шаблон `pattern:[a-f0-9]{3}` оточений дужками для застосування квантифікатора `pattern:{1,2}`. -На прикладі: +Код у дії: ```js run let regexp = /#([a-f0-9]{3}){1,2}/gi; @@ -16,7 +16,7 @@ let str = "color: #3f3; background-color: #AA00ef; and: #abcd"; alert( str.match(regexp) ); // #3f3 #AA00ef #abc ``` -Бачимо невелику проблему: патерн знайшов `match:#abc` в `subject:#abcd`. Для запобігання цьому, додамо в кінці `pattern:\b`: +Бачимо невелику проблему: вираз знайшов `match:#abc` в `subject:#abcd`. Для запобігання цьому, додамо в кінці `pattern:\b`: ```js run let regexp = /#([a-f0-9]{3}){1,2}\b/gi; diff --git a/9-regular-expressions/11-regexp-groups/04-parse-expression/solution.md b/9-regular-expressions/11-regexp-groups/04-parse-expression/solution.md index a86ad8b76..ed5526628 100644 --- a/9-regular-expressions/11-regexp-groups/04-parse-expression/solution.md +++ b/9-regular-expressions/11-regexp-groups/04-parse-expression/solution.md @@ -2,7 +2,7 @@ Оператором слугуватиме `pattern:[-+*/]`. Дефіс `pattern:-` стоїть першим в квадратних дужках, бо позиція посередині означає діапазон знаків, тоді як нам потрібен лише `-`. -Варто уникати символу `/` всередині регулярного виразу JavaScript `pattern:/.../`, зробимо це потім. +Символ `/` має бути екранованим всередині регулярного виразу JavaScript `pattern:/.../`, зробимо це потім. Нам потрібне число, оператор, тоді ще одне число. Та можливі пробіли між ними. @@ -15,7 +15,7 @@ Аби зробити кожну з цих частин окремим елементом масиву результатів, помістимо їх в круглі дужки: `pattern:(-?\d+(\.\d+)?)\s*([-+*/])\s*(-?\d+(\.\d+)?)`. -На прикладі: +Код у дії: ```js run let regexp = /(-?\d+(\.\d+)?)\s*([-+*\/])\s*(-?\d+(\.\d+)?)/; @@ -23,7 +23,7 @@ let regexp = /(-?\d+(\.\d+)?)\s*([-+*\/])\s*(-?\d+(\.\d+)?)/; alert( "1.2 + 12".match(regexp) ); ``` -Вміст результату: +Розглянемо результат: - `result[0] == "1.2 + 12"` (повний збіг) - `result[1] == "1.2"` (перша група `(-?\d+(\.\d+)?)` -- перше число, включаючи десяткову частину) diff --git a/9-regular-expressions/11-regexp-groups/04-parse-expression/task.md b/9-regular-expressions/11-regexp-groups/04-parse-expression/task.md index eb8476db9..a84860ce5 100644 --- a/9-regular-expressions/11-regexp-groups/04-parse-expression/task.md +++ b/9-regular-expressions/11-regexp-groups/04-parse-expression/task.md @@ -1,4 +1,4 @@ -# Парсинг виразу +# Розберіть вираз Арифметичний вираз складається з двох чисел та оператору між ними, наприклад: @@ -11,7 +11,7 @@ Додаткові пробіли можуть бути на початку, в кінці чи всередині виразу. -Напишіть функцію `parse(expr)`, яка приймає вираз та повертає масив з 3 елементів: +Напишіть функцію `parse(expr)`, яка приймає вираз та повертає масив з 3-ьох елементів: 1. Перше число. 2. Оператор. diff --git a/9-regular-expressions/11-regexp-groups/article.md b/9-regular-expressions/11-regexp-groups/article.md index d3a4aad19..a870060cc 100644 --- a/9-regular-expressions/11-regexp-groups/article.md +++ b/9-regular-expressions/11-regexp-groups/article.md @@ -1,11 +1,11 @@ # Групи захоплення -Частину патерну можна поставити в круглі дужки `pattern:(...)`. Це називається "група захоплення". +Частину виразу можна обгорнути в круглі дужки `pattern:(...)`. Це називається "група захоплення". Такий прийом має два наслідки: 1. Він дозволяє отримати частину збігу в якості окремого елементу в масиві результатів. -2. Якщо ми поставимо квантифікатор після дужок, він застосується до всього вмісту дужок. +2. Якщо ми поставимо квантифікатор після дужок, він застосується до всього їх вмісту. ## Приклади @@ -13,9 +13,9 @@ ### Приклад: gogogo -Без круглих дужок, патерн `pattern:go+` означає символ `subject:g`, за яким слідує `subject:o` на повторі один чи кілька разів. Тобто, `match:goooo` чи `match:gooooooooo`. +Без круглих дужок, вираз `pattern:go+` означає символ `subject:g`, за яким слідує `subject:o` на повторі один чи кілька разів. Тобто, `match:goooo` чи `match:gooooooooo`. -Круглі дужки об’єднують символи в групи, тож `pattern:(go)+` значить `match:go`, `match:gogo`, `match:gogogo` і так далі. +Круглі дужки об’єднують символи в групи, тож `pattern:(go)+` означає `match:go`, `match:gogo`, `match:gogogo` і так далі. ```js run alert( 'Gogogo now!'.match(/(go)+/ig) ); // "Gogogo" @@ -23,7 +23,7 @@ alert( 'Gogogo now!'.match(/(go)+/ig) ); // "Gogogo" ### Приклад: домен -Зробимо дещо складніше – регулярний вираз для пошуку домену сайту. +Зробимо дещо складніше -- регулярний вираз для пошуку домену сайту. Наприклад: @@ -33,7 +33,7 @@ users.mail.com smith.users.mail.com ``` -Як бачимо, домен складається з повторюваних слів та крапки після кожного з них(окрім останнього). +Як бачимо, домен складається з повторюваних слів та крапки після кожного з них (окрім останнього). В регулярних виразах це `pattern:(\w+\.)+\w+`: @@ -45,15 +45,15 @@ alert( "site.com my.site.com".match(regexp) ); // site.com,my.site.com Пошук працює, але патерн не збігатиметься з доменом з дефісом: наприклад, `my-site.com`, бо дефіс не належить до класу `pattern:\w`. -Ми можемо виправити це, замінивши `pattern:\w` на `pattern:[\w-]` в кожному слові(окрім останнього): `pattern:([\w-]+\.)+\w+`. +Ми можемо виправити це, замінивши `pattern:\w` на `pattern:[\w-]` в кожному слові (окрім останнього): `pattern:([\w-]+\.)+\w+`. ### Приклад: email -Минулий приклад можна розширити. Спираючись на нього, ми можемо створити регулярний вираз для адрес електронної пошти. +Попередній приклад можна розширити. Спираючись на нього, ми можемо створити регулярний вираз для адрес електронної пошти. Формат електронної пошти: `name@domain`. Name може бути будь-яким словом, дефіси та крапки допускаються. В регулярних виразах це `pattern:[-.\w]+`. -Патерн є наступним: +Вираз є наступним: ```js run let regexp = /[-.\w]+@([\w-]+\.)+[\w-]+/g; @@ -61,13 +61,13 @@ let regexp = /[-.\w]+@([\w-]+\.)+[\w-]+/g; alert("my@mail.com @ his@site.com.uk".match(regexp)); // my@mail.com, his@site.com.uk ``` -Це неідеальний регулярний вираз, але здебільшого робочий та здатний виправити випадкові помилки. Єдина справді надійна перевірка електронної пошти – відправити листа. +Це неідеальний регулярний вираз, але здебільшого робочий та здатний виправити випадкові помилки. Єдина справді надійна перевірка електронної пошти -- відправка листа. ## Вміст дужок всередині збігу -Дужки нумеруються зліва направо. Пошукова система запам’ятовує вміст збігу для кожної з них та дозволяє отримати його всередині результату. +Дужки нумеруються зліва направо. Пошукова система запам'ятовує вміст збігу для кожної з них та дозволяє отримати його всередині результату. -У випадку, якщо `regexp` не містить прапору `g`, метод `str.match(regexp)` шукає перший збіг та повертає його в якості масиву: +У випадку, якщо `regexp` не містить прапорця `g`, метод `str.match(regexp)` шукає перший збіг та повертає його як масив: 1. Індекс `0`: повний збіг. 2. Індекс `1`: вміст перших дужок. @@ -78,7 +78,7 @@ alert("my@mail.com @ his@site.com.uk".match(regexp)); // my@mail.com, his@site.c Огорнемо внутрішній вміст у круглі дужки, ось так: `pattern:<(.*?)>`. -Тепер ми отримаємо як тег в цілому(`match:

`), так і його вміст(`match:h1`) в отриманому масиві: +Тепер ми отримаємо як тег в цілому `match:

`, так і його вміст `match:h1` в отриманому масиві: ```js run let str = '

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

'; @@ -93,11 +93,11 @@ alert( tag[1] ); // h1 Дужки можуть бути вкладеними. В нашому випадку, нумерація також проводиться зліва направо. -Наприклад, під час пошуку тегу в `subject:`, ми можемо бути зацікавленими в: +Наприклад, під час пошуку тегу в `subject:`, нас може цікавити: 1. Вміст тегу загалом: `match:span class="my"`. -2. Імені тегу: `match:span`. -3. Атрибутах тегу: `match:class="my"`. +2. Ім'я тегу: `match:span`. +3. Атрибути тегу: `match:class="my"`. Додамо до них дужки: `pattern:<(([a-z]+)\s*([^>]*))>`. @@ -105,7 +105,7 @@ alert( tag[1] ); // h1 ![](regexp-nested-groups-pattern.svg) -На практиці: +Код у дії: ```js run let str = ''; @@ -119,7 +119,7 @@ alert(result[2]); // span alert(result[3]); // class="my" ``` -Повний збіг завжди представлений в нульовому індексі `result`. +Повний збіг завжди представлений в елементі з нульовим індексом в `result`. Далі йдуть групи, нумеровані зліва направо за відкриваючою дужкою. Перша група розміщена в `result[1]`. В даному випадку, вона охоплює весь вміст тегу. @@ -169,7 +169,7 @@ alert( match[2] ); // c Поліфіл може бути обов’язковим, такий як . ``` -Коли ми шукаємо всі збіги (прапор `pattern:g`), метод `match` не повертає вміст для груп. +Коли ми шукаємо всі збіги (прапорець `pattern:g`), метод `match` не повертає вміст для груп. Для прикладу, знайдемо всі теги в рядку: @@ -187,18 +187,18 @@ alert( tags ); //

,

Його додали в JavaScript набагато пізніше за `match` в якості "нової та покращеної версії". -Як і `match`, метод шукає збіги, але з урахуванням 3 відмінностей: +Як і `match`, метод шукає збіги, але з урахуванням 3-ьох відмінностей: 1. Він повертає не масив, а ітерований об’єкт. -2. За наявності прапору `pattern:g`, він повертає кожен збіг у вигляді масиву з групами. -3. Якщо збігів нема, він повертає замість `null` порожній ітерований об’єкт. +2. За наявності прапорцю `pattern:g`, він повертає кожен збіг у вигляді масиву з групами. +3. Якщо збігів немає, він повертає замість `null` порожній ітерований об’єкт. Наприклад: ```js run let results = '

'.matchAll(/<(.*?)>/gi); -// results – є не масивом, а ітерованим об’єктом +// results - є не масивом, а ітерованим об’єктом alert(results); // [object RegExp String Iterator] alert(results[0]); // undefined (*) @@ -223,7 +223,7 @@ for(let result of results) { } ``` -...Або використовуємо деструктурування: +...Або використаємо деструктуроване присвоєння: ```js let [tag1, tag2] = '

'.matchAll(/<(.*?)>/gi); @@ -243,18 +243,18 @@ alert( tag1.input ); //

``` ```smart header="Чому результатом `matchAll` є ітерований об’єкт, а не масив?" -Чому цей метод так спроектовано? Причина проста – заради оптимізації. +Чому цей метод так спроектовано? Причина проста - заради оптимізації. Виклик `matchAll` не проводить пошуку. Натомість, повертається ітерований об’єкт, спочатку без результатів. Пошук проводиться кожного разу ми проходимось об’єктом, наприклад, всередині циклу. Тобто, буде знайдено потрібну кількість результатів, не більше. -Наведемо приклад: потенційно, в тексті існує 100 збігів, але всередині циклу `for..of` ми знайшли 5, тоді вирішили, що цього достатньо, та викликали `break`. Тоді система не витрачатиме час на пошук 95 інших збігів. +Наведемо приклад: потенційно, в тексті існує 100 збігів, але всередині циклу `for..of` ми знайшли лише 5, тоді вирішили, що цього достатньо, та викликали `break`. Тоді система не витрачатиме час на пошук 95 інших збігів. ``` ## Іменовані групи -Пам’ятати групи за номерами важко. З простими патернами впоратись можна, але з підвищенням рівня комплексності рахувати дужки стає незручно. Існує кращий варіант: дати імена круглим дужкам. +Пам’ятати групи за номерами важко. З простими виразами впоратись можна, але з підвищенням рівня складності рахувати дужки стає незручно. Існує кращий варіант: дати імена круглим дужкам. Робиться це за допомогою `pattern:?` одразу після відкриваючої дужки. @@ -302,10 +302,10 @@ for(let result of results) { Наприклад, ```js run -let str = "Іван Зубр"; +let str = "John Bull"; let regexp = /(\w+) (\w+)/; -alert( str.replace(regexp, '$2, $1') ); // Зубр, Іван +alert( str.replace(regexp, '$2, $1') ); // Bull, John ``` Посилання на іменовані дужки можливе через `pattern:$`. @@ -329,10 +329,10 @@ alert( str.replace(regexp, '$.$.$') ); Для прикладу, якщо ми хочемо знайти `pattern:(go)+`, але не потребуємо вміст дужок (`go`) окремим елементом масиву, ми можемо написати: `pattern:(?:go)+`. -В прикладі нижче, ми отримуємо лише ім’я `match:Іван` окремим елементом збігу: +В прикладі нижче, ми отримуємо лише ім’я `match:John` окремим елементом збігу: ```js run -let str = "Gogogo Іван!"; +let str = "Gogogo John!"; *!* // ?: захоплення не включає в себе 'go' @@ -341,9 +341,9 @@ let regexp = /(?:go)+ (\w+)/i; let result = str.match(regexp); -alert( result[0] ); // Gogogo Іван (повний збіг) -alert( result[1] ); // Іван -alert( result.length ); // 2 (інших елементів у масиві нема) +alert( result[0] ); // Gogogo John (повний збіг) +alert( result[1] ); // John +alert( result.length ); // 2 (інших елементів у масиві немає) ``` ## Підсумки @@ -354,7 +354,7 @@ alert( result.length ); // 2 (інших елементів у масиві не Вміст, що збігається з групою, може бути отриманий в результатах: -- Метод `str.match` повертає групи захоплення лише без прапору `pattern:g`. +- Метод `str.match` повертає групи захоплення лише без прапорцю `pattern:g`. - Метод `str.matchAll` завжди повертає групи захоплення. Якщо в дужок нема імені, їх вміст доступний в масиві збігу за їх номером. Іменовані дужки також доступні через властивість `groups`. pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy