Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 21 additions & 20 deletions 9-regular-expressions/10-regexp-backreferences/article.md
Original file line number Diff line number Diff line change
@@ -1,33 +1,34 @@
# Backreferences in pattern: \n and \k
# Обратные ссылки в шаблоне: \n и \k

Capturing groups can be accessed not only in the result or in the replacement string, but also in the pattern itself.
Доступ к содержимому скобочных групп есть не только в результате или в строке замены, но и в самом шаблоне.

## Backreference by number: \n
## Обратная ссылка по номеру: \n

A group can be referenced in the pattern using `\n`, where `n` is the group number.
К группе можно обратиться в шаблоне, используя `\n`, где `\n` -- это номер группы.

To make things clear let's consider a task.
Чтобы было яснее, рассмотрим это на следующем примере.

We need to find a quoted string: either a single-quoted `subject:'...'` or a double-quoted `subject:"..."` -- both variants need to match.
Необходимо найти в тексте строку в кавычках: либо одинарных`subject:'...'`, либо двойных `subject:"..."` -- оба варианта должны работать.

How to look for them?
Как найти такие строки?

Можно добавить оба вида кавычек в квадратные скобки: `pattern:['"](.*?)['"]`, но в таком случае будут находиться строки со смешанными кавычками, например `match:"...'` и `match:'..."`. Это приведёт к ошибке, когда одна кавычка окажется внутри других, как в строке `subject:"She's the one!"`:

We can put two kinds of quotes in the pattern: `pattern:['"](.*?)['"]`, but it would find strings with mixed quotes, like `match:"...'` and `match:'..."`. That would lead to incorrect matches when one quote appears inside other ones, like the string `subject:"She's the one!"`:

```js run
let str = `He said: "She's the one!".`;

let reg = /['"](.*?)['"]/g;

// The result is not what we expect
// Результат не соответствует замыслу
alert( str.match(reg) ); // "She'
```

As we can see, the pattern found an opening quote `match:"`, then the text is consumed lazily till the other quote `match:'`, that closes the match.
Как видно, шаблон нашёл открывающую кавычку `match:"`, а после нашёл текст вплоть до следующей кавычки `match:'`, после чего поиск завершился.

To make sure that the pattern looks for the closing quote exactly the same as the opening one, we can make a groups of it and use the backreference.
Для того, чтобы шаблон искал закрывающую кавычку такую же, как и открывающую, обернём открывающие кавычки в скобочную группу и используем обратную ссылку на неё:

Here's the correct code:
Вот верный код:

```js run
let str = `He said: "She's the one!".`;
Expand All @@ -39,20 +40,20 @@ let reg = /(['"])(.*?)\1/g;
alert( str.match(reg) ); // "She's the one!"
```

Now it works! The regular expression engine finds the first quote `pattern:(['"])` and remembers the content of `pattern:(...)`, that's the first capturing group.
Теперь работает! Движок регулярных выражений находит первую кавычку из шаблона `pattern:(['"])` и запоминает её. Это первая скобочная группа.

Further in the pattern `pattern:\1` means "find the same text as in the first group", exactly the same quote in our case.
Далее в шаблоне `pattern:\1` означает "найти то же самое, что в первой скобочной группе", а именно -- аналогичную кавычку в нашем случае.

Please note:
Обратите внимание на два нюанса:

- To reference a group inside a replacement string -- we use `$1`, while in the pattern -- a backslash `\1`.
- If we use `?:` in the group, then we can't reference it. Groups that are excluded from capturing `(?:...)` are not remembered by the engine.
- Чтобы использовать скобочную группу в строке замены, нужно использовать ссылку вида `$1`, а в шаблоне – обратный слэш: `\1`.
- Мы не можем обращаться к группе, если в ней используется `?:`. Группы, которые помечены `(?:...)`, не запоминаются движком.

## Backreference by name: `\k<name>`
## Обратная ссылка по имени: `\k<name>`

For named groups, we can backreference by `\k<name>`.
Обратные ссылки с помощью `\k<name>` возможны для именованных групп.

The same example with the named group:
Ниже пример с именованной группой:

```js run
let str = `He said: "She's the one!".`;
Expand Down