# 正则表达式

Source: https://codewiki.com/zh/cheatsheets/regex/

## 字面文本

- `/cat/` — 在输入中任意位置匹配连续出现的字面量 `cat`
- `/a\.b/` — 转义点号，使其匹配字面字符 `.`
- `/https?:\/\//` — 匹配 `http://` 或 `https://`
- `/\n/` — 匹配一个换行符（LF）
- `/\x41/` — 用两位十六进制转义匹配 `A`
- `/\u{1F600}/u` — 在 Unicode 模式下匹配码点 `U+1F600`

## 字符集合

- `/[abc]/` — 匹配集合中一个 UTF-16 代码单元
- `/[^abc]/` — 匹配集合之外的一个 UTF-16 代码单元
- `/[a-z]/` — 匹配一个 ASCII 小写字母
- `/\d/` — 匹配一个 ASCII 数字
- `/\w/` — 匹配一个 ASCII 字母、数字或下划线
- `/\s/` — 匹配一个 ECMAScript 空白字符或行终止符
- `/\p{Letter}/u` — 匹配一个属性为 `Letter` 的 Unicode 码点

## 量词

- `/a?/` — 匹配零个或一个 `a`，优先匹配一个
- `/a*/` — 贪婪匹配零个或多个 `a`
- `/a+/` — 贪婪匹配一个或多个 `a`
- `/a{3}/` — 恰好匹配三个 `a`
- `/a{2,}/` — 至少匹配两个 `a`
- `/a{2,4}/` — 匹配二至四个 `a`，优先匹配四个
- `/a+?/` — 在后续模式允许的前提下尽量少匹配 `a`

## 位置与边界

- `/^text/` — 仅在输入开头匹配 `text`
- `/text$/` — 在输入末尾或最终行终止符之前匹配 `text`
- `/^text/m` — 在输入开头或行终止符之后匹配 `text`
- `/text$/m` — 在输入末尾或行终止符之前匹配 `text`
- `/\bword\b/` — 要求 `word` 两侧都是 ASCII 单词边界
- `/\Bword/` — 要求 `word` 之前没有 ASCII 单词边界

## 分组与反向引用

- `/(cat|dog)/` — 选择一个分支，并将其捕获为第 1 组
- `/(?:cat|dog)/` — 对分支分组，但不创建捕获
- `/(?<kind>cat|dog)/` — 将选中的分支捕获为 `groups.kind`
- `/((a)b)/` — 按左括号出现的顺序为嵌套捕获编号
- `/([a-z]+)-\1/` — 要求 `-` 后的文本与第 1 组完全相同
- `/(?<word>[a-z]+)\s+\k<word>/i` — 用命名反向引用查找重复的 ASCII 单词

## 环视

- `/q(?=u)/` — 仅当后面是 `u` 时匹配 `q`，但不消耗 `u`
- `/q(?!u)/` — 仅当后面不是 `u` 时匹配 `q`
- `/(?<=\$)\d+/` — 匹配前面带 `$` 的数字，但不消耗 `$`
- `/(?<!\$)\b\d+/` — 匹配前面没有紧邻 `$` 的 ASCII 数字
- `/^(?!.*forbidden).*$/s` — 拒绝包含字面文本 `forbidden` 的任何输入
- `/(?<!\w)cat(?!\w)/` — 匹配两侧没有紧邻 ASCII 单词字符的 `cat`

## 标志

- `/cat/i` — 匹配字母时忽略大小写
- `/^cat$/m` — 让 `^` 和 `$` 识别行边界
- `/a.b/s` — 让点号可以匹配行终止符
- `/cat/g` — 启用连续匹配和有状态的 `lastIndex`
- `/cat/d` — 在匹配结果中加入起止索引对
- `/\p{Script=Greek}+/u` — 启用 Unicode 匹配和属性转义
- `/[\p{Letter}&&\p{Script=Greek}]+/v` — 在 Unicode Sets 模式下对两个属性求交集

## 匹配结果

- `/cat/.test(text)` — 返回是否存在匹配的布尔值
- `/(?<id>\d+)/.exec(text)` — 返回首个带命名捕获的详细匹配；没有匹配时返回 `null`
- `text.match(/\d+/)` — 返回首个详细匹配；没有匹配时返回 `null`
- `text.match(/\d+/g)` — 返回所有完整匹配但不含捕获详情；没有匹配时返回 `null`
- `[...text.matchAll(/(?<id>\d+)/g)]` — 收集每次匹配的详细结果
- `match.groups.id` — 读取名为 `id` 的捕获值
- `match.indices[0]` — 使用 `d` 时读取完整匹配的 `[start, end]` 索引对

## 搜索、拆分与替换

- `text.search(/error/i)` — 返回首个匹配的索引；没有匹配时返回 `-1`
- `text.split(/\s*,\s*/)` — 按逗号拆分，并去掉逗号两侧的空白
- `text.replace(/\s+/g, ' ')` — 把每段连续空白替换成一个空格
- `text.replace(/(\d{4})-(\d{2})-(\d{2})/, '$3/$2/$1')` — 在首个匹配中重排三个编号捕获
- `text.replace(/(?<last>\w+), (?<first>\w+)/, '$<first> $<last>')` — 在首个匹配中重排命名捕获
- `text.replace(/\w+/g, word => word.toUpperCase())` — 为每个 ASCII 单词计算替换文本

## 构造与状态

- `RegExp.escape(input)` — 转义运行时文本，以便按字面量插入模式
- `new RegExp(RegExp.escape(input), 'u')` — 构造把 `input` 当作字面量的 Unicode 模式
- `pattern.source` — 读取不含分隔符和标志的模式文本
- `pattern.flags` — 按规范顺序读取已启用的标志
- `pattern.lastIndex` — 读取下一次全局或粘连匹配的起始位置
- `pattern.lastIndex = 0` — 复用全局或粘连模式前重置状态
- `new RegExp(pattern.source, pattern.flags)` — 克隆模式，并把 `lastIndex` 重置为零

## 文本检查

- `/^[A-Za-z][A-Za-z0-9_]*$/` — 校验单行输入中的 ASCII 标识符
- `/^\d+$/` — 校验单行输入中的一个或多个 ASCII 数字
- `/^\p{Decimal_Number}+$/u` — 校验单行输入中的 Unicode 十进制数字
- `/^\s*$/u` — 检查输入是否为空或完全由空白组成
- `/\r\n|[\n\r\u2028\u2029]/` — 匹配一个 ECMAScript 换行序列
- `/[ \t]+$/gm` — 查找每行末尾的空格或制表符
- `/\bTODO\b/g` — 查找作为完整 ASCII 单词的 `TODO`
