文章目录
正则表达式引擎
DFA
Deterministic finite automaton 确定型有穷自动机
NFA
Non-deterministic finite automaton 非确定型有穷自动机
- Traditional NFA
- POSIX NFA
字符串的组成
对于字符串“abc”而言,包括三个字符和四个位置。
占有字符和零宽度
表达式类型 | 判断依据 | 是否互斥 |
---|---|---|
占有字符表达式 | 匹配字符,且保存到匹配结果总 | 互斥 |
零宽度表达式 | 匹配位置,或不保存到结果中 | 非互斥 |
- 正则表达式匹配过程中,如果子表达式匹配到的是字符内容,而非位置,并被保存到最终的匹配结果中,那么就认为这个子表达式是占有字符的;如果子表达式匹配的仅仅是位置,或者匹配的内容并不保存到最终的匹配结果中,那么就认为这个子表达式是零宽度的。
- 占有字符是互斥的,零宽度是非互斥的。也就是一个字符,同一时间只能由一个子表达式匹配,而一个位置,却可以同时由多个零宽度的子表达式匹配。
控制权和传动
正则的匹配过程,通常情况下都是由一个子表达式(可能为一个普通字符、元字符或元字符序列组成)取得控制权,从字符串的某一位置开始尝试匹配,一个子表达式开始尝试匹配的位置,是从前一子表达匹配成功的结束位置开始的。
如正则表达式:
(子表达式一)(子表达式二)
- 假设(子表达式一)为零宽度表达式,由于它匹配开始和结束的位置是同一个,如位置0,那么(子表达式二)是从位置0开始尝试匹配的。
- 假设(子表达式一)为占有字符的表达式,由于它匹配开始和结束的位置不是同一个,如匹配成功开始于位置0,结束于位置2,那么(子表达式二)是从位置2开始尝试匹配的。
对于整个表达式来说,通常是由字符串位置0开始尝试匹配的。如果在位置0开始的尝试,匹配到字符串某一位置时整个表达式匹配失败,那么引擎会使正则向前传动,整个表达式从位置1开始重新尝试匹配,依此类推,直到报告匹配成功或尝试到最后一个位置后报告匹配失败。
匹配过程
xxx
零宽断言
零宽断言正如它的名字一样,是一种零宽度的匹配,它匹配到的内容不会保存到匹配结果中去,最终匹配结果只是一个位置而已。
作用是给指定位置添加一个限定条件,用来规定此位置之前或者之后的字符必须满足限定条件才能使正则中的字表达式匹配成功。
注意:这里所说的子表达式并非只有用小括号括起来的表达式,而是正则表达式中的任意匹配单元。
javascript只支持零宽先行断言,而零宽先行断言又可以分为正向零宽先行断言,和负向零宽先行断言。
正向零宽断言
(?=exp)
零宽度正预测先行断言
(?<=exp)
零宽度正回顾后发断言
例子
负向零宽断言
与正向零宽断言相反,匹配
(?!exp)
零宽度负预测先行断言
(?<!exp)
零宽度负回顾后发断言
例子
元字符
^
匹配开始
$
匹配结束
[]
匹配单个字符
()
匹配分组字符串
|
在()表示或
.
匹配任意字符
{}
匹配个数,{1,2}
{1,}
{,2}
{2}
?
模式之后,表示0个或1个 {0,1}
+
模式之后,表示1个或多个 {1,}
*
模式之后,表示0个、1个或多个 {0,}
\
转义字符
位置字符
\b
非边界
\d
数字
\w
字母+数字
字符集
[a-zA-Z0-9]
字符集 | 简写 | 字符 |
---|---|---|
字目数字 | \w | [a-zA-Z0-9] |
数字 | \d | [0-9] |
空字符 | \s | 空格、tab、换行[\t\r\n] |
字符转义
分组group
在结果中选择
$&
全部
$n
第n个分组
$`
匹配前的内容
$'
匹配后的内容
$$
$字符
处理选项
名称 | 说明 |
---|---|
IgnoreCase(忽略大小写) | 匹配时不区分大小写。 |
Multiline(多行模式) | 更改^和 的 含 义 , 使 它 们 分 别 在 任 意 一 行 的 行 首 和 行 尾 匹 配 , 而 不 仅 仅 在 整 个 字 符 串 的 开 头 和 结 尾 匹 配 。 ( 在 此 模 式 下 , 的含义,使它们分别在任意一行的行首和行尾匹配,而不仅仅在整个字符串的开头和结尾匹配。(在此模式下, 的含义,使它们分别在任意一行的行首和行尾匹配,而不仅仅在整个字符串的开头和结尾匹配。(在此模式下,的精确含意是:匹配\n之前的位置以及字符串结束前的位置.) |
Singleline(单行模式) | 更改.的含义,使它与每一个字符匹配(包括换行符\n)。 |
IgnorePatternWhitespace(忽略空白) | 忽略表达式中的非转义空白并启用由#标记的注释。 |
ExplicitCapture(显式捕获) | 仅捕获已被显式命名的组。 |
贪婪与非贪婪
规则
- 最先开始的匹配拥有最高的优先权——The match that begins earliest wins。
字符串:aabb
匹配模式:a.*?b
匹配aab,而不是ab - 默认是贪婪模式,即在满足这个表达式的前提系啊,尽可能多的匹配更多的字符
常用表达式
- 排除
/^(?!.*\.(js|css|jpg|jpeg|png|gif).*)/
- 数字分组替换
/\B(?=(?:\d{3})+(?!\d))/g
// 结果:1,234,567,890,匹配的是后面是3*n个数字的非单词边界(\B)
"1234567890".replace(/\B(?=(?:\d{3})+(?!\d))/g,",");
- 匹配汉字
[\u4e00-\u9fa5]
- 匹配双字节字符(包括汉字在内)
[^\x00-\xff]
- 一个正则表达式,只含有汉字、数字、字母、下划线不能以下划线开头和结尾:
^(?!_)(?!.*?_$)[a-zA-Z0-9_\u4e00-\u9fa5]+$
参考
glob简介
正则基础之——NFA引擎匹配原理
正则表达式中(?:pattern)、(?=pattern)、(?!pattern)、(?<=pattern)和(?<!pattern)
正则表达式测试-开源中国工具
中文正则表达式匹配
正则表达式零宽断言详解
一个奇怪的现象
/.*?/g
匹配 abc
会匹配 "abc"
和 ""
一个空字符串