前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >正则表达式的用法及原理

正则表达式的用法及原理

原创
作者头像
Ritchie
修改2022-08-18 15:09:26
1.2K1
修改2022-08-18 15:09:26
举报
文章被收录于专栏:Ritchie的专栏Ritchie的专栏

由于工作中和正则表达式打交道比较多,所以花了几天的时间系统学习了正则,在此总结一下。

正则表达式:是一种非常强大的文本处理工具

主要用途:

1.校验数据的有效性(验证手机号、邮箱、身份证号等)

2.用于查询或者匹配符合的文本内容(语音助手query正则召回、egrep查询日志等)

3.对文本进行切割、替换等操作

基本语法:

三种匹配模式:贪婪匹配、非贪婪匹配、独占匹配

1.贪婪匹配:表示次数的量词默认是贪婪的,在贪婪模式下,会竟可能最大长度的去匹配

对于text = 'aaabb'

regex = 'a+' 匹配结果:'aaa'

regex = 'a*' 匹配结果:'aaa','','',''

按照text下标从0开始,试着分析下:

代码语言:javascript
复制
i. [0-3] 匹配'aaa' 到b的时候不满足
ii. [3,3]匹配剩下的'bb',匹配不了,返回空串
iii. [4,4]匹配剩下的'b',匹配不了,返回空串
iv. [5,5]匹配剩下的空串,返回空串

2.非贪婪匹配:在量词后面加上问号(?),就变成非贪婪匹配

这个regex本意都是查找被""括起来的内容,第一张图只有量词+这种情况下就是贪婪匹配,匹配了整个字符串;第二张图在量词+后添加了?这样就变成了非贪婪匹配,匹配了两个字符串

3.独占模式:贪婪模式和非贪婪模式都需要回溯,在有些场景下不需回溯,匹配不上就返回失败,给量词后面加上+,就可以变成独占匹配

regex = 'xy{1,3}z'

text = 'xyyz'

i. 贪婪匹配:y{1,3}最大长度的匹配y,直到去匹配text中的z失败后,吐出text中的z(回溯),然后再用正则中的z去匹配text中的z

ii. 非贪婪匹配:=> regex = 'xy{1,3}?z',y{1,3}? 最小长度的匹配y,匹配了xy之后,用正则中的z去匹配字符串中的z不匹配,正则回溯到y{1,3}?继续来匹配y,匹配成功

iii. 独占匹配:=> regex = 'xy{1,3}+yz',如图就只匹配一个text,不回溯

分组与引用

一般来说我们会把以()括起来的看做一个整体,也即分组的概念

代码语言:javascript
复制
比如:2022-06-29 21:29:30
写一个简单的正则来匹配的话:regex = (\d{4}-\d{2}-\d{2}) (\d{2}:\d{2}:\d{2}
该正则并不严谨,只是为了说明,这里第几个左括号就表示第几个分组(即第几个分组编号),默认下根据圆括号分完组的子组会保存,方便被后面进行引用

引用的语法:+'分组编号' , 如regex = '(\w+) \1' 能够匹配连续两个相同的word,\1即分组引用的语法

另:如果不想保存子组的话,可以使用(?:regex表达式)来不保存子组

多分支选择时,左边优先

regex = '北京|北京市',text = '北京市' 如下图并不匹配,因此要想匹配北京市可以regex = '北京市|北京' 或者是把公共部分提取出来 regex = 北京市?

常见的4中匹配模式

正则中的断言:对匹配到的文本有位置要求,以下图为例:想要匹配11为数字的手机号,但是我输入14位数字的话,前11位是可以匹配的

1.单词边界(word boundary)

eg: regex = 'tom'

text = 'tom will go hiking tomorrow'

其实是匹配了两次, 第一次是tom,第二次是tomorrow的前半部分

语法:\b

代码语言:javascript
复制
regex = 'tom' 包含tom的word
regex = '\btom' 以tom开头的word
regex = 'tom\b' 以tom结尾的word
regex = '\btom\b' 只匹配tom

如果要准确匹配某个word的话,就可以使用(\b\w+\b)

2.行的开始和结束 ^$

3.环视(look around) 要求匹配部分的前面或者后面要满足/不满足某种规则

注:环视虽然有括号,但是不会保存为子组(只表示对文本左右环境的要求,只匹配位置,并不关心其他)

正则相关历史,两个流派

正则匹配原理

正则能够处理复杂文本由于有穷状态自动机(finite automanton).

自动机是指系统可以根据相应的条件,在不同的状态下进行转移(1个系统有有穷个状态,不同状态代表不同的含义,每次的操作如输入字符串,可能会使状态转移)

有穷自动机分为DFA(determinstic finite automanton)和NFA(non-determinstic finite automanton)

代码语言:javascript
复制
NFA工作机制:先看正则后看文本
regex = 'xiao(ai|mi|du|ma)'
text = 'i work at xiaomi'
从正则表达式的第一个字符x,在text文本中查找x,匹配后直到走到字符o,接着用第一个分支ai中的a去匹配text文本中的m,匹配失败,第一个分支ai结束,用第二个分支mi的第一个字符m继续和text文本匹配,最终匹配成功,那么剩下的第三、四个分支就不用继续匹配了,类似于Java中&&的短路逻辑
DFA工作机制:先看文本后看正则
regex = 'xiao(ai|mi|du|ma)'
text = 'i work at xiaomi'
从text文本的第一个字符i开始去匹配regex的第一个字符x,不匹配,继续向后走,直到匹配完xiao,在匹配多分支结构时为并行的匹配,同时去用text文本中的字符m分别匹配a,m,d,匹配不上的该分支就结束,最终就分支mi胜出,匹配成功

未完待续......

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档