# regex

## 一次匹配一个的字符

| 表达式         | 含义                                                                      |
| -------------- | ------------------------------------------------------------------------- |
| `.`            | 任意字符                                                                  |
| `[abc]`        | （在…之内）包含 `a` 、 `b` 或 `c` 的任何字符（和 `a \| b \| c` 作用相同） |
| `[a-zA-Z]`     | （在…之内）从 `a` 到 `z` 、 `A` 到 `Z` 的任何一个字符                     |
| `[^abc]`       | （除…之外）除 `a` 、 `b` 、 `c` 之外的任何一个字符                        |
| `[abc[hij]]`   | （并） `a` 、 `b` 、 `c` 、 `h` 、 `i` 、 `j` 中的任意字符                |
| `[a-z&&[hij]]` | （交） `h` 、 `i` 或 `j` 中的某一个字符                                   |
| `\s`           | 空白符（空格、tab、换行、换页、回车）                                     |
| `\S`           | 非空白符（ `[^\s]` ）                                                     |
| `\d`           | 数字（ `[0-9]` ）                                                         |
| `\D`           | 非数字（ `[^0-9]` ）                                                      |
| `\w`           | 词字符（ `[a-zA-Z_0-9]` ）                                                |
| `\W`           | 非词字符（ `[^\w]` ）                                                     |
| `\t`           | 制表符Tab                                                                 |
| `\n`           | 换行符                                                                    |
| `\r`           | 回车                                                                      |
| `\\`           | 反斜杠                                                                    |

## 一次匹配多个字符

| 贪婪型   | 勉强型    | 占有型    | 如何匹配                         |
| -------- | --------- | --------- | -------------------------------- |
| `X?`     | `X??`     | `X?+`     | 一个或零个 `X`                   |
| `X*`     | `X*?`     | `X*+`     | 零个或多个 `X`                   |
| `X+`     | `X+?`     | `X++`     | 一个或多个 `X`                   |
| `X{n}`   | `X{n}?`   | `X{n}+`   | 恰好 `n` 次 `X`                  |
| `X{n,}`  | `X{n,}?`  | `X{n,}+`  | 至少 `n` 次 `X`                  |
| `X{n,m}` | `X{n,m}?` | `X{n,m}+` | `X` 至少 `n` 次，但不超过 `m` 次 |

## 确定字符出现的位置

| 表达式 | 含义             |
| ------ | ---------------- |
| `^`    | 一行的开始       |
| `$`    | 一行的结束       |
| `\b`   | 词的边界         |
| `\B`   | 非词的边界       |
| `\G`   | 前一个匹配的结束 |

## 分组的概念

如果我们对匹配到的结果进行一些更加复杂的操作，需要了解 **分组** 的概念。

如果想访问第一个分组，就用 `$1`，如果想访问第二个分组，就用 `$2`，以此类推，最大是 `$9`。这里说的分组就是小括号，一个小括号代表一个分组。可以参考下面这段 JS 代码理解分组的应用：

```js
var re = /(\w+)\s(\w+)/;
var str = "John Smith";
str.replace(re, "$2, $1"); // "Smith, John"
RegExp.$1; // "John"
RegExp.$2; // "Smith"
```

另外一个场景是进行批量文本替换，比如用 Notepad++ 编辑文档时，针对下面这段文本，想要在以 `-` 开头的单词两侧加上双引号，那么可以使用 {numref}`regex-replace` 的规则进行批量替换。

```text
| -Ox    | 最大化选项           |
| -Og    | 启用全局优化         |
| -Oy[-] | 启用框架指针省略     |
| -Oi    | 启用内建函数         |
```

```{figure} ../_static/images/regex_replace.png
:name: regex-replace

批量替换以 `-` 开头的单词
```
