# 正则表达式语法详细总结


# 正则表达式（Regex/RegExp）语法详细总结
正则表达式是一套用于**匹配、查找、替换、校验字符串**的规则语法，被绝大多数编程语言、文本编辑器、数据库原生支持，核心是通过元字符定义匹配模式，实现精准高效的文本处理。

---

## 一、基础规则与必转义元字符
### 1. 普通字符
字母、数字、中文、下划线`_`等无特殊含义的字符，**直接匹配自身**，例如正则`abc`仅匹配字符串中的连续字符`abc`。

### 2. 特殊元字符（必须转义）
以下字符在正则中拥有专属语法含义，若要匹配字符本身，必须加反斜杠`\`转义：
```
. * + ? ^ $ | ( ) [ ] { } \
```
示例：要匹配字符串中的`.`，正则需写为`\.`，而非`.`。

---

## 二、字符类（方括号表达式）
匹配**方括号内的任意一个字符**，单次匹配仅命中一个字符，是正则的基础匹配单元。

| 语法 | 说明 | 匹配示例 |
| :--- | :--- | :--- |
| `[abc]` | 普通字符类，匹配a/b/c中的任意一个 | `[abc]at` 匹配`aat`/`bat`/`cat` |
| `[^abc]` | 否定字符类，匹配**除了**a/b/c之外的任意字符 | `[^abc]at` 匹配`dat`/`eat`，不匹配`aat`/`bat` |
| `[a-z]` | 范围字符类，匹配指定区间内的字符 | `[0-9a-fA-F]` 匹配16进制字符 |
| `.` | 通配符，匹配**除换行符`\n`外**的任意单个字符（单行模式下可匹配换行） | `h.t` 匹配`hat`/`hot`/`h t`，不匹配`heet` |

### 预定义字符类（简写）
系统预设的高频字符类，简化书写，所有预定义类均为**单个字符匹配**：

| 简写 | 等价写法 | 核心说明 |
| :--- | :--- | :--- |
| `\d` | `[0-9]` | 匹配任意数字 |
| `\D` | `[^0-9]` | 匹配任意非数字 |
| `\w` | `[a-zA-Z0-9_]` | 匹配任意单词字符（字母、数字、下划线） |
| `\W` | `[^a-zA-Z0-9_]` | 匹配任意非单词字符 |
| `\s` | `[ \t\n\r\f\v]` | 匹配任意空白字符（空格、制表符、换行等） |
| `\S` | `[^ \t\n\r\f\v]` | 匹配任意非空白字符 |

> 关键注意：方括号内的特殊元字符，除`^`(开头否定)、`-`(区间)、`\`(转义)、`]`(闭合)外，其余均无需转义，例如`[.]`仅匹配`.`本身，而非任意字符。

---

## 三、量词（重复匹配）
控制**前面的单个字符/分组**的重复出现次数，是实现批量匹配的核心，分为3种匹配模式。

### 1. 基础量词语法
| 语法 | 匹配规则 | 典型场景 |
| :--- | :--- | :--- |
| `{n}` | 前面的单元**必须恰好出现n次** | 固定长度校验，如`\d{6}`匹配6位验证码 |
| `{n,}` | 前面的单元**至少出现n次**，无上限 | 最小长度限制，如`\w{6,}`匹配至少6位单词字符 |
| `{n,m}` | 前面的单元**出现n~m次**，包含n和m | 区间长度限制，如`\d{8,16}`匹配8-16位数字 |
| `*` | 零次或多次，等价于`{0,}` | 可选重复内容，如`a.*b`匹配a开头、b结尾的任意字符串 |
| `+` | 一次或多次，等价于`{1,}` | 必选重复内容，如`\d+`匹配连续数字 |
| `?` | 零次或一次，等价于`{0,1}` | 可选内容，如`colou?r`匹配`color`和`colour` |

### 2. 贪婪 vs 非贪婪（懒惰）模式
正则默认是**贪婪模式**：尽可能匹配最长的符合规则的字符串；
在量词后加`?`，切换为**非贪婪模式**：尽可能匹配最短的符合规则的字符串。

| 模式 | 语法 | 示例 | 匹配字符串`a123b456b`的结果 |
| :--- | :--- | :--- | :--- |
| 贪婪模式 | 量词默认 | `a.*b` | 匹配整个字符串`a123b456b` |
| 非贪婪模式 | 量词+`?` | `a.*?b` | 仅匹配最短片段`a123b` |

### 3. 占有模式
在量词后加`+`，语法如`*+`/`++`/`{n,m}+`，匹配时**一次性吞入所有符合规则的字符，匹配失败不回溯**，性能更高，仅PCRE、Java等引擎支持，JS原生不支持。

---

## 四、锚点与边界匹配（零宽匹配）
**零宽度核心特性**：仅匹配字符串中的**位置**，不匹配任何字符，不消耗字符串长度，核心用于限定匹配内容的位置。

| 语法 | 名称 | 匹配规则 |
| :--- | :--- | :--- |
| `^` | 行开头锚点 | 匹配字符串的开头；多行模式`m`下，匹配每一行的开头 |
| `$` | 行结尾锚点 | 匹配字符串的结尾；多行模式`m`下，匹配每一行的结尾 |
| `\b` | 单词边界 | 匹配单词字符(`\w`)和非单词字符(`\W`)之间的位置 |
| `\B` | 非单词边界 | 匹配两个单词字符/两个非单词字符之间的位置，与`\b`相反 |
| `\A` | 字符串绝对开头 | 仅匹配整个字符串的开头，不受多行模式`m`影响 |
| `\Z` | 字符串结尾 | 仅匹配整个字符串的结尾，或结尾换行符前的位置，不受多行模式影响 |
| `\z` | 字符串绝对结尾 | 仅匹配整个字符串的最末尾，忽略结尾换行符 |

核心示例：
- `^\d{6}$`：匹配整个字符串恰好是6位数字，用于表单验证码校验
- `\bhello\b`：匹配独立单词`hello`，不匹配`helloworld`中的`hello`
- `hello$`：仅匹配一行末尾的`hello`

---

## 五、分组与捕获
用圆括号`()`将多个字符/规则打包为一个整体，可对整个分组施加量词、分支，同时可捕获分组匹配的内容供后续使用。

### 1. 捕获分组
普通括号`()`会将分组内匹配的内容**捕获并存储**，系统自动按左括号的顺序从`1`开始编号，`0`固定为整个正则匹配的完整内容。

| 语法 | 说明 | 示例 |
| :--- | :--- | :--- |
| `(pattern)` | 普通捕获分组，自动编号 | `(\d{4})-(\d{2})-(\d{2})`：匹配日期，分组1=年，分组2=月，分组3=日 |
| `(?<name>pattern)` | 命名捕获分组，自定义分组名 | `(?<year>\d{4})-(?<month>\d{2})`：给年、月分组命名，JS/Java/.NET支持 |
| `(?P<name>pattern)` | Python专属命名捕获分组 | Python中通过`group('name')`获取对应匹配内容 |

### 2. 非捕获分组
语法`(?:pattern)`，仅用于**分组打包，不捕获内容，不占用分组编号**，适合仅需分组控制量词/分支、无需后续引用的场景，可节省内存、提升匹配效率。

示例：
- `(?:ab)+`：匹配`ab`重复1次或多次（如`ababab`），但不捕获`ab`的内容
- `http(?:s)?://`：匹配`http://`和`https://`，`s`可选，无需捕获

### 3. 分支结构（或）
语法`|`，匹配`|`左右任意一个模式，**优先级极低**，低于量词和锚点，通常需配合分组使用。

示例：
- 正确写法：`gr(a|e)y`，匹配`gray`和`grey`，精准限定分支范围
- 错误写法：`gra|ey`，匹配`gra`或`ey`，而非预期的两个单词

---

## 六、反向引用
引用**前面捕获分组匹配到的内容（而非模式本身）**，实现重复内容的精准匹配，是正则的核心进阶能力。

### 1. 编号反向引用
语法`\数字`，数字对应捕获分组的编号，例如`\1`引用第1个捕获组，`\2`引用第2个。

核心示例：
- `(\w+)\s+\1`：匹配连续重复的单词，如`hello hello`、`test test`，`\1`严格匹配前面`(\w+)`捕获到的内容
- `<(\w+)>.*?</\1>`：匹配闭合HTML标签，如`<div>123</div>`，`\1`引用前面的标签名`div`

### 2. 命名反向引用
对应命名捕获组，不同引擎语法不同：
- JS/Java/.NET：`\k<name>`，示例`(?<tag>\w+).*?\k<tag>`
- Python：`(?P=name)`，示例`(?P<tag>\w+).*?(?P=tag)`

> 关键提醒：反向引用的是**分组匹配到的具体内容**，而非分组的规则。例如`(\d)\1`匹配`11`、`22`，但不匹配`12`，因为`\1`必须和第一个分组的内容完全一致。

---

## 七、零宽断言（环视/Lookaround）
进阶零宽匹配，**仅匹配位置，不消耗字符**，核心是判断「当前位置的前后」是否符合指定模式，是实现精准条件匹配的核心能力。

| 断言类型 | 语法 | 匹配规则 | 核心说明 |
| :--- | :--- | :--- | :--- |
| 正向先行断言 | `(?=pattern)` | 匹配**后面紧跟**pattern的位置 | 向右看，符合条件才匹配 |
| 负向先行断言 | `(?!pattern)` | 匹配**后面不紧跟**pattern的位置 | 向右看，不符合条件才匹配 |
| 正向后行断言 | `(?<=pattern)` | 匹配**前面紧跟**pattern的位置 | 向左看，符合条件才匹配 |
| 负向后行断言 | `(?<!pattern)` | 匹配**前面不紧跟**pattern的位置 | 向左看，不符合条件才匹配 |

### 核心示例
1. 正向先行断言：`\d+(?=元)`，匹配`100元`中的`100`，不匹配`100块`中的`100`
2. 负向先行断言：`\d+(?!元)`，匹配`100块`中的`100`，不匹配`100元`中的`100`
3. 正向后行断言：`(?<=￥)\d+`，匹配`￥100`中的`100`，不匹配`$100`中的`100`
4. 负向后行断言：`(?<!￥)\d+`，匹配`$100`中的`100`，不匹配`￥100`中的`100`

### 高频实战场景
密码强度校验：必须同时包含大小写字母、数字，长度8-16位
```regex
^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z0-9]{8,16}$
```
- 多个先行断言叠加，分别校验必须包含小写、大写、数字，再匹配主体规则

### 兼容性说明
- 先行断言：所有主流引擎均支持
- 后行断言：JS ES2018+、Python 3.10+、Java、.NET支持；低版本JS/Python仅支持固定长度的后行断言，不支持`*`/`+`等不定长规则

---

## 八、修饰符（标志位）
写在正则表达式的末尾，用于**全局控制匹配模式**，不同语言的写法略有差异（JS：`/pattern/flags`；Python：`re.compile(pattern, flags)`）。

| 修饰符 | 全称 | 核心作用 |
| :--- | :--- | :--- |
| `i` | Ignore Case | 忽略大小写，匹配时不区分字母大小写 |
| `g` | Global | 全局匹配，找到所有符合规则的匹配项，而非仅第一个 |
| `m` | Multiline | 多行模式，`^`和`$`匹配每一行的开头和结尾，而非整个字符串 |
| `s` | Dot All / Singleline | 单行模式，通配符`.`可以匹配换行符`\n`，默认不匹配 |
| `u` | Unicode | Unicode模式，支持匹配4字节的Unicode字符（如emoji、生僻字） |
| `x` | Extended | 扩展模式，忽略正则中的空白字符，支持行内注释，提升可读性 |

示例：
- `/hello/i`：匹配`Hello`、`HELLO`、`hello`
- `/\d+/g`：匹配字符串中所有的数字序列，而非仅第一个

---

## 九、特殊转义字符
用于匹配不可见字符、特殊编码字符，常用如下：

| 语法 | 匹配内容 |
| :--- | :--- |
| `\t` | 水平制表符（Tab键） |
| `\n` | 换行符 |
| `\r` | 回车符 |
| `\f` | 换页符 |
| `\v` | 垂直制表符 |
| `\0` | 空字符（NULL） |
| `\xhh` | 两位十六进制ASCII字符，如`\x41`匹配`A` |
| `\uhhhh` | 四位十六进制Unicode字符，如`\u4e2d`匹配中文`中` |
| `\cX` | 控制字符，X为A-Z，如`\cM`匹配Ctrl+M（回车符） |

---

## 十、高级语法与特殊构造
以下为进阶语法，不同正则引擎的支持度差异较大，主流PCRE、Java、.NET支持，部分JS低版本不支持。

### 1. 条件匹配
语法：`(?(id/name)yes-pattern|no-pattern)`
含义：如果指定编号/名称的捕获组匹配成功，则匹配`yes-pattern`，否则匹配`no-pattern`，`|no-pattern`可选。

示例：`(<)?a.*?(?(1)>)`：匹配`<a href="xxx">`或`a href="xxx"`，如果开头有`<`，结尾必须有`>`。

### 2. 原子组（固化分组）
语法：`(?>pattern)`
含义：一次性吞入匹配的内容，**匹配失败时不回溯**，大幅提升正则性能，避免灾难性回溯。

示例：`(?>a+)ab`匹配`aaaab`时，先吞入所有`a`，发现后续无法匹配`ab`，直接失败，不回溯释放`a`。

### 3. 正则注释
语法：`(?#注释内容)`
含义：正则内的注释，不参与匹配，配合`x`修饰符可实现多行注释，提升复杂正则的可读性。

示例：`\d{4}(?#年)-\d{2}(?#月)-\d{2}(?#日)`

### 4. 递归匹配
语法：`(?R)`/`(?0)`
含义：递归引用整个正则表达式本身，用于匹配嵌套结构（如嵌套括号、嵌套HTML标签）。

示例：`\(([^()]+|(?R))*\)`：匹配任意深度的嵌套括号，如`(a(b(c)d)e)`。

---

## 十一、正则运算符优先级（从高到低）
正则的匹配顺序由优先级决定，优先级从高到低排序如下，避免书写时出现逻辑错误：
1. 转义符：`\`
2. 括号类：`()`、`(?:)`、`(?=)`、`[]`（方括号字符类）
3. 量词：`*`、`+`、`?`、`{n}`、`{n,}`、`{n,m}`
4. 锚点与字符序列：`^`、`$`、`\b`、普通字符、预定义字符类
5. 分支结构：`|`（或）

> 核心提醒：`|`的优先级最低，若要限定分支范围，必须用括号包裹，否则会作用于整个正则的左右两侧。

---

## 十二、高频常用正则示例
| 场景 | 正则表达式 |
| :--- | :--- |
| 手机号（中国大陆） | `^1[3-9]\d{9}$` |
| 邮箱地址 | `^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$` |
| 身份证号（18位） | `^[1-9]\d{5}(19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[0-9Xx]$` |
| 中文匹配 | `^[\u4e00-\u9fa5]+$` |
| URL地址 | `^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)$` |
| 强密码（8-20位，含大小写+数字+特殊字符） | `^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*])[a-zA-Z0-9!@#$%^&*]{8,20}$` |

---

## 十三、常见误区与避坑指南
1. **方括号内的通配符失效**：`[.]`仅匹配`.`本身，而非任意字符，方括号内绝大多数元字符无需转义。
2. **贪婪与非贪婪混淆**：默认贪婪模式会匹配最长结果，提取内容时需用非贪婪模式`.*?`避免越界。
3. **反向引用规则误解**：反向引用的是分组匹配到的**内容**，而非分组的正则规则。
4. **锚点缺失导致校验失效**：表单校验时必须加`^`和`$`，否则只要字符串中包含符合规则的片段就会匹配成功，例如`\d{6}`会匹配`abc123456def`，而`^\d{6}$`仅匹配纯6位数字。
5. **分支优先级错误**：`ab|cd`匹配`ab`或`cd`，而非`a(b|c)d`，需用括号限定分支范围。
6. **灾难性回溯**：嵌套的贪婪量词（如`(a+)*`）会导致匹配失败时出现指数级回溯，造成程序卡死，需用原子组、非贪婪模式优化。


