正则表达式语法:
.匹配任意字符
-指定范围,如1-9代表1到9之间的所有数字
*代表匹配零次或多次之前的段落 AB*表示A,AB,ABB,ABBB等
+代表匹配多次之前的段落 AB+表示AB,ABB,ABBB等
?代表之前的字符可有可无 AB?表示A,AB
|表示或者,("A"|"B")表示字符A或字符B
^a只能匹配以小写字母为行首的行: "a..."
a$ 只能匹配以小写字母为行尾的行: "...a"
^a$只能匹配a
()为括号内的为一组,优先运算
[] 为字符集合,[ABc]匹配的字符为ABc,括号中的^代表否定,[^ABC]代表除了ABC之外的所有字符
{} 指出一个模式可能出现的次数,{1,5}代表前面段落出现为1到5次
\s为空白符,\S为非空白符,则[\s\S]代表所有字符
\w匹配字母、数字、下划线
\d匹配所有数字单个字符,\D匹配所有非数字单个字符
\b:表示字母数字与非字母数字的边界, 非字母数字与字母数字的边界。
\B:表示字母数字与(非非)字母数字的边界,非字母数字与非字母数字的边界。
另外如果文本中有正则表达式的关键字,那么加\表示转义,那么\\代表斜杠本身,\.代表需要匹配文本中的.
[\u4e00-\u9fa5]为中文字符匹配
运算优先级:
从高到低:
转义符>圆括号和方括号>限定符>定位点和序列(即:位置和顺序)>或
\>(), (?:), (?=), []>*, +, ?, {n}, {n,}, {n,m}>^, $, \char>|
零宽断言:
两个正则表达式提取出想要的内容完全可以用零宽断言处理
(?=exp) 零宽度正预测先行断言,后面为exp才匹配,但是不算在捕获组中
(?<=exp) 零宽度正回顾后发断言,前面为exp才匹配,但是不算在捕获组中
(?!exp) 零宽度负预测先行断言,前面不为exp才匹配,但是不算在捕获组中
(?<!exp) 零宽度负回顾后发断言,后面不为exp才匹配,但是不算在捕获组中
举几个栗子:
零宽度正预测先行断言
123hello
456hello
789hello
如何只匹配前面是456的hello匹配呢
(?<=456)hello
零宽度正回顾后发断言
123hello
456hello
789hello
如何只匹配前面不是456的hello匹配呢
(?<!456)hello
零宽度负预测先行断言
hello123
hello456
hello789
如何只匹配后面是456的hello匹配呢
hello(?=456)
零宽度负回顾后发断言
hello123
hello456
hello789
如何只匹配后面不是456的hello匹配呢
hello(?!456)
简单的例子:
IP地址正则表达式:
^((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$
首先IP地址的区间为0.0.0.0~255.255.255.255
250-255 有 25[0-5]
200-249 有 2[0-4]\d
0-200 有 [01]?\d\d?
0-255就有(25[0-5]|2[0-4]\d|[01]?\d\d?)
.在正则表达式中有含义,那加上\则表示原来的字符
前三个末尾带“.”,重复三次就有((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}
再带上末尾的就有((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)
加上前后定位符即可以判断是否这段字符串为正则表达式
^((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$
底层原理:
自动机有三种匹配模式:贪婪模式、懒惰模式、独占模式
常用的NFA自动机,该自动机具有贪婪特性,会尽可能匹配多的字符
举个简单的例子:
string="Today is a nice day."
regex="day"
首先拿d和T匹配发现不成立,再拿d和o作比较也不匹配,往后,d匹配,再看第二个字符a符合,如此找到匹配项目day
大概原理就是这样,实际上会做很多优化,但是其原理不变
回溯会花费CPU资源
贪婪模式:
string="ABBC"
regex="AB{1,3}C"
正则表达式中的B{1,3}会匹配string的前两个BB,也会比较第三个C,然后发现不同,就会回溯,最后开始C的匹配,匹配成功
当B{1,3}后面加了“?”,以后就会变成懒惰模式:
string="ABBC"
regex="AB{1,3}?C"
正则表达式中的B{1,3}会匹配string的第一个B,然后就会拿regex的C和string的第二个B比较,发现不匹配,就会回溯,然后再拿B{1,3}再和string的第二个B和第三个B做比较,最后匹配成功
当在B{1,3}之后加多一个 + 符号,那么原先的贪婪模式就会变成独占模式,就不会发生回溯了
string="ABBC"
regex="AB{1,3}+BC"
B{1,3}把两个B全占据了,结果string中的C和regex的BC做匹配结果发现无法匹配
优化字符匹配效率:
当用户输入的字符串过大的时候,会产生大量回溯,在保证正确的情况下可以将其转换为独占模式,可大量减少回溯,减少CPU消耗率
下面是正则表达式在C++中的调用: