Skip to content

Commit

Permalink
Merge pull request #420 from MrsMelnychenko/regex-quantificators
Browse files Browse the repository at this point in the history
Quantifiers +, *, ? and {n}
  • Loading branch information
dolgachio authored Jan 4, 2023
2 parents cda70e7 + 024d5ea commit 8716e2e
Showing 1 changed file with 52 additions and 52 deletions.
104 changes: 52 additions & 52 deletions 9-regular-expressions/09-regexp-quantifiers/article.md
Original file line number Diff line number Diff line change
@@ -1,142 +1,142 @@
# Quantifiers +, *, ? and {n}
# Квантифікатори +, *, ? та {n}

Let's say we have a string like `+7(903)-123-45-67` and want to find all numbers in it. But unlike before, we are interested not in single digits, but full numbers: `7, 903, 123, 45, 67`.
Припустимо, у нас є рядок `+38(067)-123-45-67` і нам потрібно знайти всі числа в ньому. Але цього разу, на відміну від попередніх, нас цікавлять не поодинокі цифри, а саме числа : `38, 067, 123, 45, 67`.

A number is a sequence of 1 or more digits `pattern:\d`. To mark how many we need, we can append a *quantifier*.
Число це послідовність з 1, або більше цифр `pattern:\d` і щоб позначити потрібну нам кількість, ми можемо застосувати *квантифікатор*.

## Quantity {n}
## Кількість {n}

The simplest quantifier is a number in curly braces: `pattern:{n}`.
Найпростішим квантифікатором є число у фігурних дужках: `pattern:{n}`.

A quantifier is appended to a character (or a character class, or a `[...]` set etc) and specifies how many we need.
Квантифікатор додається до символу(або класу символів, набору `[...]`, тощо) і позначає яка їх кількість нам потрібна.

It has a few advanced forms, let's see examples:
Існує декілька способів використання квантифікатора, розглянемо на прикладах:

The exact count: `pattern:{5}`
: `pattern:\d{5}` denotes exactly 5 digits, the same as `pattern:\d\d\d\d\d`.
Точна кількість: `pattern:{5}`
: `pattern:\d{5}` означає точно 5 цифр, так само як і `pattern:\d\d\d\d\d`.

The example below looks for a 5-digit number:
Нижченаведений приклад шукатиме число, яке складається з 5-ти цифр:

```js run
alert( "I'm 12345 years old".match(/\d{5}/) ); // "12345"
alert( "Мені 12345 років".match(/\d{5}/) ); // "12345"
```

We can add `\b` to exclude longer numbers: `pattern:\b\d{5}\b`.
Ми могли б додати `\b` і таким чином вилучити з пошуку числа довші за наш шаблон: `pattern:\b\d{5}\b`.

The range: `pattern:{3,5}`, match 3-5 times
: To find numbers from 3 to 5 digits we can put the limits into curly braces: `pattern:\d{3,5}`
Діапазон: `pattern:{3,5}`, від 3 до 5
: Щоб знайти числа, які складаються з мінімум 3 і максимум 5 чисел, ми можемо вказати потрібні обмеження у фігурних дужках: `pattern:\d{3,5}`

```js run
alert( "I'm not 12, but 1234 years old".match(/\d{3,5}/) ); // "1234"
alert( "Мені не 12 років, а 1234".match(/\d{3,5}/) ); // "1234"
```

We can omit the upper limit.
Ми можемо не вказувати верхню межу.

Then a regexp `pattern:\d{3,}` looks for sequences of digits of length `3` or more:
В такому випадку, регулярний вираз `pattern:\d{3,}` шукатиме послідовність цифр довжиною від `3` і/або більше:

```js run
alert( "I'm not 12, but 345678 years old".match(/\d{3,}/) ); // "345678"
alert( "Мені не 12, а 345678 років".match(/\d{3,}/) ); // "345678"
```

Let's return to the string `+7(903)-123-45-67`.
Давайте повернемось до рядка `+38(067)-123-45-67`.

A number is a sequence of one or more digits in a row. So the regexp is `pattern:\d{1,}`:
Число це послідовність з однієї або більше цифр підряд. Таким чином, регулярний вираз виглядатиме `pattern:\d{1,}`:

```js run
let str = "+7(903)-123-45-67";
let str = "+38(067)-123-45-67";

let numbers = str.match(/\d{1,}/g);

alert(numbers); // 7,903,123,45,67
alert(numbers); // 38,067,123,45,67
```

## Shorthands
## Скорочення

There are shorthands for most used quantifiers:
Існують способи скорочено записати більшу частину часто вживаних квантифікаторів:

`pattern:+`
: Means "one or more", the same as `pattern:{1,}`.
: Означає "один, або більше", так само як і `pattern:{1,}`.

For instance, `pattern:\d+` looks for numbers:
До прикладу, `pattern:\d+` шукає числа, які складаються з однієї, або більше цифр:

```js run
let str = "+7(903)-123-45-67";
let str = "+38(067)-123-45-67";

alert( str.match(/\d+/g) ); // 7,903,123,45,67
alert( str.match(/\d+/g) ); // 38,067,123,45,67
```

`pattern:?`
: Means "zero or one", the same as `pattern:{0,1}`. In other words, it makes the symbol optional.
: Означає "нуль, або один", так само як і `pattern:{0,1}`. Інакше кажучи, в такий спосіб ми робимо символ необов'язковим.

For instance, the pattern `pattern:ou?r` looks for `match:o` followed by zero or one `match:u`, and then `match:r`.
До прикладу, шаблон `pattern:ou?r` шукатиме літеру `match:o` після якої, можливо, йтиме літера `match:u`, і потім літера `match:r`.

So, `pattern:colou?r` finds both `match:color` and `match:colour`:
І таким чином, `pattern:colou?r` знайде обидва слова `match:color` та `match:colour`:

```js run
let str = "Should I write color or colour?";
let str = "Англійською слово колір пишеться як color чи colour?";

alert( str.match(/colou?r/g) ); // color, colour
```

`pattern:*`
: Means "zero or more", the same as `pattern:{0,}`. That is, the character may repeat any times or be absent.
: Означає "нуль, або більше", так само, як і `pattern:{0,}`. Це означає, що символ може бути відсутнім, або повторюватись безліч разів.

For example, `pattern:\d0*` looks for a digit followed by any number of zeroes (may be many or none):
До прикладу, `pattern:\d0*` шукає цифру, після якої йде будь-яка кількість нулів (може бути багато, або жодного):

```js run
alert( "100 10 1".match(/\d0*/g) ); // 100, 10, 1
```

Compare it with `pattern:+` (one or more):
Порівняйте з `pattern:+` (один, або більше):

```js run
alert( "100 10 1".match(/\d0+/g) ); // 100, 10
// 1 not matched, as 0+ requires at least one zero
// Регулярний вираз не знайшов 1, оскільки 0+ вимагає наявності щонайменше одного нуля
```

## More examples
## Більше прикладів

Quantifiers are used very often. They serve as the main "building block" of complex regular expressions, so let's see more examples.
Квантифікатори використовуються дуже часто. Вони основні "будівельні блоки" складних регулярних виразів, тож розглянемо ще декілька прикладів.

**Regexp for decimal fractions (a number with a floating point): `pattern:\d+\.\d+`**
**Регулярний вираз для десяткових дробів (чисел з плаваючою комою): `pattern:\d+\.\d+`**

In action:
В дії:
```js run
alert( "0 1 12.345 7890".match(/\d+\.\d+/g) ); // 12.345
```

**Regexp for an "opening HTML-tag without attributes", such as `<span>` or `<p>`.**
**Регулярний вираз для "відкриваючого HTML-тегу без атрибутів", наприклад, `<span>`, або `<p>`.**

1. The simplest one: `pattern:/<[a-z]+>/i`
1. Найпростіший варіант: `pattern:/<[a-z]+>/i`

```js run
alert( "<body> ... </body>".match(/<[a-z]+>/gi) ); // <body>
```

The regexp looks for character `pattern:'<'` followed by one or more Latin letters, and then `pattern:'>'`.
Регулярний вираз шукає символ `pattern:'<'` після якого йдуть одна, або більше літер латиницею, а потім `pattern:'>'`.

2. Improved: `pattern:/<[a-z][a-z0-9]*>/i`
2. Покращений варіант: `pattern:/<[a-z][a-z0-9]*>/i`

According to the standard, HTML tag name may have a digit at any position except the first one, like `<h1>`.
Згідно стандарту, назва HTML-тегу може містити в собі і цифру на будь-якій позиції окрім першої, як наприклад `<h1>`.

```js run
alert( "<h1>Hi!</h1>".match(/<[a-z][a-z0-9]*>/gi) ); // <h1>
```

**Regexp "opening or closing HTML-tag without attributes": `pattern:/<\/?[a-z][a-z0-9]*>/i`**
**Регулярний вираз "відкриваючого, або закриваючого HTML-тегу без атрибутів": `pattern:/<\/?[a-z][a-z0-9]*>/i`**

We added an optional slash `pattern:/?` near the beginning of the pattern. Had to escape it with a backslash, otherwise JavaScript would think it is the pattern end.
Ми додали необов'язковий слеш `pattern:/?` на початку шаблону і для того, щоб JavaScript не сприйняв його як кінець регулярного виразу, нам довелось його екранувати.
```js run
alert( "<h1>Hi!</h1>".match(/<\/?[a-z][a-z0-9]*>/gi) ); // <h1>, </h1>
```
```smart header="To make a regexp more precise, we often need make it more complex"
We can see one common rule in these examples: the more precise is the regular expression -- the longer and more complex it is.
```smart header="Щоб зробити регулярний вираз більш точним, нам часто доводиться його ускладнювати"
На прикладах ми побачили, що більш точним є регулярний вираз, тим довшим і складнішим є його реалізація.
For instance, for HTML tags we could use a simpler regexp: `pattern:<\w+>`. But as HTML has stricter restrictions for a tag name, `pattern:<[a-z][a-z0-9]*>` is more reliable.
До прикладу, для HTML-тегів без атрибутів ми могли б використати простіший регулярний вираз: `pattern:<\w+>`. Але так як HTML має більш жорсткі вимоги до назв тегів, то шаблон `pattern:<[a-z][a-z0-9]*>` буде більш точним.
Can we use `pattern:<\w+>` or we need `pattern:<[a-z][a-z0-9]*>`?
Чи можемо ми використовувати `pattern:<\w+>` чи краще писати `pattern:<[a-z][a-z0-9]*>`?
In real life both variants are acceptable. Depends on how tolerant we can be to "extra" matches and whether it's difficult or not to remove them from the result by other means.
В реальному життя обидва варіанти мають право на існування. Все залежить від того, чи готові ми допустити "зайві" співпадіння з нашим регулярний виразом і наскілльки важко, або легко буде відфільтрувати їх і отримати перелік потрібних нам співпадінь.
```

0 comments on commit 8716e2e

Please sign in to comment.