目录

正则表达式语法详细总结

正则表达式(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匹配colorcolour

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,匹配graygrey,精准限定分支范围
  • 错误写法:gra|ey,匹配graey,而非预期的两个单词

六、反向引用

引用前面捕获分组匹配到的内容(而非模式本身),实现重复内容的精准匹配,是正则的核心进阶能力。

1. 编号反向引用

语法\数字,数字对应捕获分组的编号,例如\1引用第1个捕获组,\2引用第2个。

核心示例:

  • (\w+)\s+\1:匹配连续重复的单词,如hello hellotest 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匹配1122,但不匹配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位

^(?=.*[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:匹配HelloHELLOhello
  • /\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
中文匹配 ^[\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匹配abcd,而非a(b|c)d,需用括号限定分支范围。
  6. 灾难性回溯:嵌套的贪婪量词(如(a+)*)会导致匹配失败时出现指数级回溯,造成程序卡死,需用原子组、非贪婪模式优化。