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

Backreferences in pattern: \N and \k<name> #592

Merged
merged 3 commits into from
Feb 2, 2020
Merged
Show file tree
Hide file tree
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
2 changes: 1 addition & 1 deletion 1-js/06-advanced-functions/01-recursion/article.md
Original file line number Diff line number Diff line change
Expand Up @@ -504,7 +504,7 @@ list.next = list.next.next;

当然,链表不总是优于数组。不然大家都去使用链表了。

主要的不足就是我们无法轻易通过它的编号获取元素。在数组中却很容易:`arr[n]` 是一个直接引用。而在列表中,我们需要从起点元素顺着 `next` 找 `N` 次才能获取到第 N 个元素。
主要的不足就是我们无法轻易通过它的编号获取元素。在数组中却很容易:`arr[n]` 是一个直接引用。而在链表中,我们需要从起点元素顺着 `next` 找 `N` 次才能获取到第 N 个元素。

...但是我们并不总需要这样的操作。比如,当我们需要一个队列或者甚至一个[双向队列](https://en.wikipedia.org/wiki/Double-ended_queue) —— 有序结构必须可以快速的从两端添加、移除元素。

Expand Down
2 changes: 1 addition & 1 deletion 1-js/10-error-handling/1-try-catch/article.md
Original file line number Diff line number Diff line change
Expand Up @@ -653,7 +653,7 @@ try {
- `name` —— 异常名称(异常对象的构造函数的名称)。
- `stack`(没有标准) —— 异常发生时的调用栈。

我们也可以通过使用 `throw` 运算符来生成自定义的异常。技术上来讲,`throw` 的参数没有限制,但是通常它是一个继承自内置的 `Error` 类的异常对象。更对关于异常的扩展,请看下个章节。
我们也可以通过使用 `throw` 运算符来生成自定义的异常。技术上来讲,`throw` 的参数没有限制,但是通常它是一个继承自内置的 `Error` 类的异常对象。更多关于异常的扩展,请看下个章节。

重新抛出异常,是一种异常处理的基本模式:`catch` 代码块通常处理某种已知的特定类型的异常,所以它应该抛出其他未知类型的异常。

Expand Down
44 changes: 22 additions & 22 deletions 9-regular-expressions/12-regexp-backreferences/article.md
Original file line number Diff line number Diff line change
@@ -1,33 +1,33 @@
# Backreferences in pattern: \N and \k<name>
# 模式中的反向引用:\N \k<name>

We can use the contents of capturing groups `pattern:(...)` not only in the result or in the replacement string, but also in the pattern itself.
我们不仅可以在结果或替换字符串中使用捕获组 `pattern:(...)` 的内容,还可以在模式本身中使用它们。

## Backreference by number: \N
## 按编号反向引用:\N

A group can be referenced in the pattern using `pattern:\N`, where `N` is the group number.
可以使用 `pattern:\N` 在模式中引用一个组,其中 `N` 是组号。

To make clear why that's helpful, let's consider a task.
为了弄清那为什么有帮助,让我们考虑一项任务。

We need to find quoted strings: either single-quoted `subject:'...'` or a double-quoted `subject:"..."` -- both variants should match.
我们需要找到带引号的字符串:单引号 `subject:'...'` 或双引号 `subject:"..."`– 应匹配两种变体。

How to find them?
如何找到它们?

We can put both kinds of quotes in the square brackets: `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 in the string `subject:"She's the one!"`:
我们可以将两种引号放在方括号中:`pattern:['"](.*?)['"]`,但它会找到带有混合引号的字符串,例如 `match:"...'` `match:'..."`。当一种引号出现在另一种引号内,比如在字符串 `subject:"She's the one!"` 中时,便会导致不正确的匹配:

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

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

// The result is not what we'd like to have
// 不是我们想要的结果
alert( str.match(regexp) ); // "She'
```

As we can see, the pattern found an opening quote `match:"`, then the text is consumed 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 wrap it into a capturing group and backreference it: `pattern:(['"])(.*?)\1`.
为了确保模式查找的结束引号与开始的引号完全相同,我们可以将其包装到捕获组中并对其进行反向引用:`pattern:(['"])(.*?)\1`

Here's the correct code:
这是正确的代码:

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

Now it works! The regular expression engine finds the first quote `pattern:(['"])` and memorizes its content. 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` 在模式中进一步的含义是“查找与第一(捕获)分组相同的文本”,在我们的示例中为完全相同的引号。

Similar to that, `pattern:\2` would mean the contents of the second group, `pattern:\3` - the 3rd group, and so on.
与此类似,`pattern:\2` 表示第二(捕获)分组的内容,`pattern:\3` – 第三分组,依此类推。

```smart
If we use `?:` in the group, then we can't reference it. Groups that are excluded from capturing `(?:...)` are not memorized by the engine.
如果我们在组中使用 `?:`,那么我们将无法引用它。用 `(?:...)` 捕获的组被排除,引擎不会存储。
```

```warn header="Don't mess up: in the pattern `pattern:\1`, in the replacement: `pattern:$1`"
In the replacement string we use a dollar sign: `pattern:$1`, while in the pattern - a backslash `pattern:\1`.
```warn header="不要搞混了: 在模式中用 `pattern:\1`,在替换项中用:`pattern:$1`"
在替换字符串中我们使用美元符号:`pattern:$1`,而在模式中 - 使用反斜杠 `pattern:\1`
```

## Backreference by name: `\k<name>`
## 按命名反向引用:`\k<name>`

If a regexp has many parentheses, it's convenient to give them names.
如果正则表达式中有很多括号对(注:捕获组),给它们起个名字方便引用。

To reference a named group we can use `pattern:\k<имя>`.
要引用命名组,我们可以使用:`pattern:\k<name>`。

In the example below the group with quotes is named `pattern:?<quote>`, so the backreference is `pattern:\k<quote>`:
在下面的示例中引号组命名为 `pattern:?<quote>`,因此反向引用为 `pattern:\k<quote>`

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