基于 JS/PCRE 风格,适用于 VS Code 搜索(ripgrep 引擎)。
| 语法 | 含义 |
|---|---|
. |
任意单个字符(默认不含换行) |
\d |
数字 [0-9] |
\D |
非数字 [^0-9] |
\w |
单词字符 [a-zA-Z0-9_] |
\W |
非单词字符 |
\s |
空白字符(空格、tab、换行等) |
\S |
非空白字符 |
\t |
制表符 |
\n |
换行符 |
\r |
回车符 |
\\ |
转义反斜杠本身 |
\. \( \[ 等 |
转义特殊字符,匹配字面量 |
| 语法 | 含义 |
|---|---|
[abc] |
匹配 a、b 或 c |
[^abc] |
不匹配 a、b、c |
[a-z] |
a 到 z 范围 |
[a-zA-Z0-9] |
字母和数字 |
[^a-z] |
非小写字母 |
| 语法 | 含义 |
|---|---|
* |
0 次或多次(贪婪) |
+ |
1 次或多次(贪婪) |
? |
0 次或 1 次 |
{n} |
恰好 n 次 |
{n,} |
至少 n 次 |
{n,m} |
n 到 m 次 |
*? |
0 次或多次(懒惰/非贪婪) |
+? |
1 次或多次(懒惰) |
{n,m}? |
n 到 m 次(懒惰) |
贪婪 vs 懒惰:
# 贪婪:匹配尽可能多
".*" 对 "a" and "b" → 匹配整个 "a" and "b"
# 懒惰:匹配尽可能少
".*?" 对 "a" and "b" → 分别匹配 "a" 和 "b"
| 语法 | 含义 |
|---|---|
^ |
行首 |
$ |
行尾 |
\b |
单词边界 |
\B |
非单词边界 |
| 语法 | 含义 |
|---|---|
(abc) |
捕获组,替换时用 $1 引用 |
(?:abc) |
非捕获组(仅分组,不捕获,不占编号) |
(?<name>abc) |
命名捕获组,替换时用 $<name> 引用 |
\1 \2 |
反向引用第 1、2 个捕获组 |
\k<name> |
反向引用命名捕获组 |
(a\|b) |
或匹配 |
(?:...)分组但不捕获,不占用 $1 编号。常用于只需要分组逻辑但不需要引用的场景。
# 捕获组:
(https?)://(\w+)
# $1 = https, $2 = example
# 非捕获组:
(?:https?)://(\w+)
# $1 直接就是 example,协议部分不占编号
\1 \2在同一个正则表达式内部引用前面捕获组匹配到的实际内容。用于匹配"重复出现的相同文本"。
# 查找连续重复单词(比如 "the the")
\b(\w+)\s+\1\b
# \1 引用第一个捕获组匹配到的实际内容
# "the the" → 匹配 ?
# "the that" → 不匹配 ?
# 查找 HTML 中开闭标签匹配的元素
<(\w+)>.*?</\1>
# <div>hello</div> → 匹配 ?
# <div>hello</span> → 不匹配 ?
注意区分:
\1用在查找表达式中(反向引用),$1用在替换表达式中(捕获引用)。
不限于 1-9,$10、\10 都可以使用。
# 假设有 10 个捕获组
(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)
\10 → 引用第 10 个组(j)
$10 → 替换时引用第 10 个组
歧义规则:如果存在第 10 个捕获组,\10 引用第 10 个;否则解释为 \1 + 字面量 "0"。为避免歧义,推荐使用命名捕获组。
(?<name>...)# 交换姓名顺序
查找:(?<last>\w+),\s*(?<first>\w+)
替换:$<first> $<last>
# "Zhang, San" → "San Zhang"
命名捕获组也支持反向引用,用 \k<name>:
# 查找重复单词(命名版本)
\b(?<word>\w+)\s+\k<word>\b
# "hello hello" → 匹配 ?
# 等价于 \b(\w+)\s+\1\b,但可读性更好
命名组同时也有编号,$1 和 $<name> 都能用:
(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})
# $<year> 等于 $1
# $<month> 等于 $2
# $<day> 等于 $3
零宽断言只做条件判断,不消耗字符,匹配结果中不包含断言部分的文本。
| 语法 | 名称 | 含义 |
|---|---|---|
(?=...) |
正向前瞻 (Positive Lookahead) | 后面必须跟着 ... |
(?!...) |
负向前瞻 (Negative Lookahead) | 后面不能跟着 ... |
(?<=...) |
正向后顾 (Positive Lookbehind) | 前面必须是 ... |
(?<!...) |
负向后顾 (Negative Lookbehind) | 前面不能是 ... |
# 正向前瞻:匹配后面跟着 "(" 的单词(找函数名)
\w+(?=\()
# "foo()" 中匹配 "foo","bar = 1" 中不匹配
# 负向前瞻:找不跟着数字的 foo
foo(?!\d)
# "fooBar" 匹配,"foo123" 不匹配
# 正向后顾:匹配前面是 "SL" 的类名部分
(?<=SL)\w+
# "SLGameView" 中匹配 "GameView"
# 负向后顾:匹配前面不是字母的数字
(?<![a-zA-Z])\d+
# "x100" 中不匹配,"= 100" 中匹配 "100"
注意:VS Code(ripgrep)中后顾要求模式是固定长度的,不能在
(?<=...)里用*或+等不定长量词。
VS Code 搜索栏中通过按钮切换。在代码中写正则时,标志加在末尾(如 /pattern/flags)。
| 标志 | 含义 |
|---|---|
i |
大小写不敏感 |
g |
全局匹配(找所有,不只第一个) |
m |
多行模式,^$ 匹配每行的开头和结尾 |
s |
单行/dotAll 模式,. 也匹配换行符 |
// i - 大小写不敏感
/hello/i
// 匹配 "Hello"、"HELLO"、"hElLo"
// g - 全局匹配
"aaa".match(/a/g) // ["a", "a", "a"]
"aaa".match(/a/) // ["a"](只找第一个)
// m - 多行模式
`line1
line2
line3`.match(/^\w+/gm) // ["line1", "line2", "line3"]
`line1
line2
line3`.match(/^\w+/g) // ["line1"](只匹配第一行开头)
// s - 单行/dotAll 模式
"a\nb".match(/a.b/) // null(. 不匹配 \n)
"a\nb".match(/a.b/s) // ["a\nb"] ?
Aa 按钮 → i 标志(大小写敏感开关)^$ 默认是多行模式(m 已开启)s 标志按钮,要让 . 匹配换行可用 [\s\S] 代替注意:以上标志示例是 JavaScript 代码中的写法,VS Code 搜索栏本身不支持写代码逻辑,只支持纯正则表达式和替换模板。
. * + ? ^ $ { } [ ] ( ) | \ /
用 \ 转义,比如匹配 C++ 要写 C\+\+。
| 语法 | 含义 |
|---|---|
$0 |
引用整个匹配 |
$1 $2 |
引用捕获组 |
$<name> |
引用命名捕获组 |
\n |
替换中插入换行 |
\u$1 |
首字母大写 |
\l$1 |
首字母小写 |
\U$1 |
全部大写 |
\L$1 |
全部小写 |
大小写转换示例:
# snake_case → camelCase
查找:(\w+)_(\w+)
替换:$1\u$2
# 全部转大写
查找:(\w+)
替换:\U$1
${n:/transform}(仅限 Snippet)⚠️ 大括号转换语法是 VS Code Snippet(代码片段)专用语法,在搜索替换(Ctrl+H)中不生效,会被当作字面量输出。搜索替换中请使用
\u\U\l\L。
大括号语法来自 TextMate/snippet 风格,用于 snippet 定义文件(.code-snippets)或 snippet 相关的场景中。
大括号内可以用编号或命名捕获组名:
| 语法 | 含义 | 适用场景 |
|---|---|---|
${1:/upcase} |
将捕获组 1 全部转大写 | Snippet |
${1:/downcase} |
将捕获组 1 全部转小写 | Snippet |
${1:/capitalize} |
将捕获组 1 首字母大写 | Snippet |
${1:/pascalcase} |
将捕获组 1 转为 PascalCase | Snippet |
${1:/camelcase} |
将捕获组 1 转为 camelCase | Snippet |
${name:/upcase} |
将命名捕获组全部转大写 | Snippet |
${name:/downcase} |
将命名捕获组全部转小写 | Snippet |
${name:/capitalize} |
将命名捕获组首字母大写 | Snippet |
${name:/pascalcase} |
将命名捕获组转为 PascalCase | Snippet |
${name:/camelcase} |
将命名捕获组转为 camelCase | Snippet |
与搜索替换中简写语法的对应关系:
| Snippet 大括号语法 | 搜索替换等价写法 |
|---|---|
${1:/upcase} |
\U$1 |
${1:/downcase} |
\L$1 |
${1:/capitalize} |
\u$1 |
${1:/pascalcase} |
无等价写法 ❌ |
${1:/camelcase} |
无等价写法 ❌ |
| 功能 | 搜索替换(Ctrl+H) | Snippet(.code-snippets) |
|---|---|---|
| 引用捕获组 | $1、$<name> |
$1、${1}、${name} |
| 全部大写 | \U$1 |
${1:/upcase} |
| 全部小写 | \L$1 |
${1:/downcase} |
| 首字母大写 | \u$1 |
${1:/capitalize} |
| 首字母小写 | \l$1 |
无 |
| PascalCase | 不支持 ❌ | ${1:/pascalcase} |
| camelCase | 不支持 ❌ | ${1:/camelcase} |
简单记:搜索替换用反斜杠(
\U\u\L\l),Snippet 用大括号(${n:/transform})。两套语法不能混用。
这两个是编程中常见的命名风格:
| 风格 | 规则 | 示例 |
|---|---|---|
| PascalCase | 每个单词首字母大写 | MyVariable、GameView、HttpRequest |
| camelCase | 第一个单词小写,后续单词首字母大写 | myVariable、gameView、httpRequest |
在 Snippet 大括号语法中,/pascalcase 和 /camelcase 会把捕获内容按分隔符(下划线、连字符、空格等)拆分成单词,然后按对应风格拼接:
输入 "hello_world"
/pascalcase → "HelloWorld"
/camelcase → "helloWorld"
输入 "my-component"
/pascalcase → "MyComponent"
/camelcase → "myComponent"
输入 "SOME_CONST"
/pascalcase → "SomeConst"
/camelcase → "someConst"
以下示例用于 .code-snippets 文件中的 snippet transform:
// snippet 中对变量做正则变换的写法:
// ${变量/正则/替换/标志}
// 文件名转 PascalCase 作为类名
"body": ["class ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/} {", "}"]
// 文件名 "my-component" → class MyComponent { }
// 文件名转 camelCase 作为变量名
"body": ["const ${TM_FILENAME_BASE/(.*)/${1:/camelcase}/} = {}"]
// 文件名 "my-component" → const myComponent = {}
// 命名捕获组 + 大括号语法
"body": ["${TM_FILENAME_BASE/(?<name>.*)/${name:/upcase}/}"]
// 文件名 "utils" → UTILS
以下示例用于 VS Code 搜索替换(Ctrl+H):
# snake_case → camelCase(手动方式,因为搜索替换不支持 /camelcase)
查找:(\w+)_(\w)(\w*)
替换:$1\u$2$3
# "my_var" → "myVar"
# 注意:只处理一个下划线,多段需要多次替换
# 全部转大写
查找:(\w+)
替换:\U$1
# 首字母大写
查找:\b(\w)(\w*)
替换:\u$1$2
# 命名捕获组 + 大小写转换
查找:(?<first>\w+),\s*(?<last>\w+)
替换:\U$<first> \L$<last>
# "hello, WORLD" → "HELLO world"
# 查找所有函数声明
\b\w+\s+\w+\(.*\)
# 查找 TODO 或 FIXME 注释
(TODO|FIXME).*
# 查找特定类的方法调用
SLGameView\.\w+
# 查找 #include 引用
#include\s+["<].*[">]
# 替换:保留参数,改函数名
查找:oldFunc\(([^)]*)\)
替换:newFunc($1)
# 替换浮点数后缀 f → F
查找:(\d+\.\d+)f
替换:$1F
# 查找连续重复单词
\b(\w+)\s+\1\b
# 交换逗号分隔的两部分
查找:(?<a>\w+),\s*(?<b>\w+)
替换:$<b>, $<a>