学习正则表达式
写在前面
这篇文章主要是根据老姚的《JavaScript正则表达式迷你书(第一版)》所做的笔记,然后根据阮老师的es6教程进行了一些扩展,算是系统的学了一遍正则。
字符匹配
横向匹配和纵向匹配
- 横向匹配 —> 同一字符,重复出现 —> 量词
{m, n}
- 纵向匹配 —> 不同字符,出现一次 —> 字符组
[abc]
- 横向匹配 —> 同一字符,重复出现 —> 量词
量词
- 简写
{m, }
—> 至少m次{m}
—> m次?
—> 出现或不出现(0次或1次)+
—> 至少1次*
—> 任意次
- 贪婪匹配与惰性匹配
直接写量词 —> 贪婪匹配 —> 匹配出所有满足条件的
量词后面加?
—> 惰性匹配 —> 只匹配出第一次满足条件的
- 简写
字符组
- 范围表示 —> 连字符
-
—>[a-z]
- 排除(不包含)表示 —> 脱字符
^
—>[^a-z]
- 常见的简写
\d
(\D
) —> 一位(非)数字 —>[0-9]
([^0-9]
)\w
(\W
) —> 一位(非)数字、字母、下划线 —>[0-9a-zA-z_]
([^0-9a-zA-z_]
)\s
(\S
) —> 一位(非)空白符 —>[ \t\v\n\r\f]
([^ \t\v\n\r\f]
).
—> 通配符,表示几乎任意字符。换行符、回车符、行分隔符和段分隔符除外。- 任意字符用
[\d\D]``[\w\W]``[\s\S]``[^]
四者之一 - es6+ 提案:增加了
s
修饰符,以支持用.
匹配所有字符。
- 范围表示 —> 连字符
多选分支
用管道符|
分割,惰性的(即匹配到一个后,之后的就不匹配)
位置匹配
- 锚点
- 匹配开头和结尾
^
和$
- 多行匹配模式(即有修饰符 m)时,匹配行开头和行结尾
- 单词边界和非单词边界
\b
和\B
- 单词边界就是
\w
和\W
之间的位置,以及\w
和^
之间的位置与\w
和$
之间的位置
- 具体位置
- p 是个子模式。
(?=p)
表示p前的位置,也就是这个位置的后面的字符必须匹配p(?!p)
表示非/不是/除了p前的位置,也就是这个位置的后面的字符必须不匹配p- es6+ 提案:
(?<=p)
和(?<!p)
表示p之后
- 匹配开头和结尾
- 特性
- 位置可理解为空字符“”
- 两个字符间的一个位置可以用重复多个锚点表示 —> 这个特点常用来限定一个位置需要满足一定的条件(比如:
(?=.*[0-9])^
表示开头之后的字符必须包含一个数字,(?=.*[0-9])
和^
都表示开头的位置)
关于括号
- 分组
将一个模式作为整体,以便后面加量词。或者将分支结构作为整体防止歧义 - 提取数据和替换
分组之后就可以方便的操作每一个分组。全局属性$1
至$9
的使用 - 反向引用
在表达式中引用之前出现的分组。\1``\2
…的使用- 括号嵌套 —> 以左括号为准
\10
—> 表示第10个分组 (表示\1
和0
,使用(?:\1)0
或者\1(?:0)
)- 引用了不存在的分组 —> 当作普通字符进行匹配字符本身
- 分组后有量词 —> 分组最终捕获到的数据是最后一次的匹配
- 非捕获括号
单纯使用括号的分组功能,不会涉及引用功能。 —> 在之前的左括号后加上?:
,即(?:p)
- es6+ 提案
- 支持为每个分组取别名。之前的用数字表示法依然有效,不冲突。
- 语法:
(?<groupName>p)
- 在正则里反向引用的语法:
\k<groupName>
- 在replace替换时引用分组的语法:
$<groupName>
- 此外,可以在
exec
方法返回结果的groups
属性上引用该组名
回溯原理
常见的回溯形式
- 贪婪量词
- 惰性量词
- 分支结构
拆分
操作符优先级(由高到低)
转义符、括号、量词、位置和序列、管道符
构建
- 平衡法则
- 匹配预期的字符串
- 不匹配非预期的字符串
- 可读性和可维护性
- 效率
- 优化方法
- 使用具体型字符组来代替通配符,消除回溯
- 使用非捕获型分组
- 独立出确定字符
- 提取分支公共部分
- 减少分支数量,缩小范围
编程
- 验证(常用
test
)!!~string.search(regex)
regex.test(string)
!!string.match(regex)
!!regex.exec(string)
- 切分
string.split(regex)
- 提取(常用
match
)string.match(regex)
regex.exec(string)
regex.test(string); console.log(RegExp.$1)
string.test(regex); console.log(RegExp.$1)
- 使用replace,将函数作为第二个参数
- 替换
replace
- 注意点
search
和match
会把字符串转换为正则match
返回结果的格式,与正则对象是否有修饰符g
有关。- 没有
g
,返回这样的数组:第一个元素是整体匹配的内容,接下来是分组捕获的内容,然后是整体匹配的第一个下标,最后是输入的目标字符串。 - 有
g
,返回所有匹配内容的数组
- 没有
- 有
g
修饰符时,exec
比match
强大exec
会记录上次匹配的位置,接着上次匹配后继续匹配。
Author: Wang He
Origin: http://wanghewanghe.github.io
Link: http://wanghewanghe.github.io/2017/10/29/学习正则表达式/
本文采用知识共享署名-非商业性使用 4.0 国际许可协议进行许可