正则表达式学习总结

1 正则元字符

1.1 特殊单字符

. 任意字符,换行除外
d 任意数字 D 任意非数字
w 任意字母数字下划线 W 任意非字母数字下划线
s 任意空白符 S 任意非空白符

1.2 空白符


 回车符

 换行符

 换页符

 制表符

 垂直制表符
s 任意空白符

1.3 量词

*含义:0到多次
+含义:1到多次
?含义:0到1次,如colou?r
{m}含义:出现m次
{m,}含义:出现至少m次
{m,n}含义:出现m到n次

1.4 范围

|或,如ab|bc代表ab或bc
[...]多选一,括号中任一单个元素
[a-z]匹配a到z之间的任意单个元素
[^...]取反,不能是括号中的任意单个元素

1.5 元字符和量词转换

元字符 同义表示方法 示例
* {0,} 0到多次
+ {1,} 1到多次
? {0,1} 0到1次

2 正则三种模式

2.1 贪婪匹配

尽可能进行最长匹配
在正则中,表示次数的量词默认是贪婪的,在贪婪模式下,会尝试尽可能最大长度去匹配。

import re
re.findall(r'a*', 'aaabb')  # 贪婪模式
['aaa', '', '', '']

2.2 非贪婪匹配

尽可能进行最短匹配
“数量”元字符后加?(英文)找出长度最小且满足要求的

import re
re.findall(r'a*?', 'aaabb') # 非贪婪模式
['', 'a', '', 'a', '', 'a', '', '', '']

2.3 独占模式

回溯:

不管是贪婪模式,还是非贪婪模式,都需要发生回溯才能完成相应的功能。但是在一些场景下,我们不需要回溯,匹配不上返回失败就好了,因此正则中还有另外一种模式,独占模式,它类似贪婪匹配,但匹配过程不会发生回溯,因此在一些场合下性能会更好。

regex="xy{1,3}z"
text="xyyz"

在匹配时,y{1,3}会尽可能长地去匹配,当匹配完 xyy 后,由于 y 要尽可能匹配最长,即三个,但字符串中后面是个 z 就会导致匹配不上,这时候正则就会向前回溯,吐出当前字符 z,接着用正则中的 z 去匹配。

量词后面加加号(+)

独占模式和贪婪模式很像,独占模式会尽可能多地去匹配,如果匹配失败就结束,不会进行回溯,这样的话就比较节省时间。具体的方法就是在量词后面加上加号(+)。
下面的例子匹配不到:

String str = "xyyz";
Pattern r = compile("xy{1,3}+yz");
Matcher m = r.matcher(str);
if(m.find()){
    System.out.println(m.group());
}

3 分组与引用

3.1 分组

括号在正则中可以用于分组,被括号括起来的部分“子表达式”会被保存成一个子组,第几个括号就是第几个分组。
括号里面的会保存成子组,在括号里面使用:?就可以不保存子组;不保存子组可以提高正则的性能。
区分第几组:
只需要数左括号(开括号)是第几个,就可以确定是第几个子组。
命名分组:

后续更改正则会使编号发生变化,所以需要命名分组规则(?P<分组名>正则)。

在java语言中示例:

Pattern r = compile("(?<分组名>正则)");

3.2 分组引用

在知道了分组引用的编号 (number)后,大部分情况下,我们就可以使用 “反斜扛 + 编号”,即 umber 的方式来进行引用,而 JavaScript 中是通过$编号来引用,如$1。

编程语言 查找时引用方式 昔换时引用方式
Python umber如1 umber如1
Java umber如1 $number如$1
JavaScript $number如$1 $number如$1

示例:

regex="(w+) 1"
text="cat cat"

4 四种匹配模式

4.1 不区分大小写模式

不区分大小写模式,它可以让整个正则或正则中某一部分进行不区分大小写的匹配。

(?i)正则

4.2 点号通配模式

点号通配模式也叫单行匹配,改变的是点号的匹配行为,让其可以匹配任何字符,包括换行。

(?s)正则

4.3 多行匹配模式

多行匹配说的是 ^ 和 $ 的匹配行为,让其可以匹配上每行的开头或结尾。

(?m)正则

4.4 注释模式

注释模式则可以在正则中添加注释,让正则变得更容易阅读和维护。

(?#word)
(w+)(?#word) 1(?#word repeat again)

5 断言

5.1 单词边界

正则中使用 来表示单词的边界,放在前面是以正则开始,放在正则后面是以正则结束。

5.2 行的开始或结束

如果我们要求匹配的内容要出现在一行文本开头或结尾,就可以使用 ^ 和 $ 来进行位置界定。
使用场景:日志信息多行根据时间确定起始位置
数据校验,只能是6位数字结尾

>>> import re
>>> re.search('d{6}', "1234567") is not None
True    <-- 能匹配上 (包含6位数字)
>>> re.search('^d{6}', "1234567") is not None
True    <-- 能匹配上 (以6位数字开头)
>>> re.search('d{6}$', "1234567") is not None
True    <-- 能匹配上 (以6位数字结尾)
>>> re.search('^d{6}$', "1234567") is not None
False   <-- 不能匹配上 (只能是6位数字)
>>> re.search('^d{6}$', "123456") is not None
True    <-- 能匹配上 (只能是6位数字)

5.3 环视

只匹配固定长度的数据且前后都有限制,比如匹配六位数字的邮政编码,则7位数字就必须匹配失败。
左尖括号代表看左边,没有尖括号是看右边,感叹号是非的意思。

正则 名称 含义 示例
(?<=Y) 肯定逆序环视 左边是Y (?<=d)th能匹配到6th
(?<!Y) 否定逆序环视 左边不是Y (?<!d)th能匹配到health
(?=Y) 肯定顺序环视 右边是Y six(?=d)th能匹配到six8
(?!Y) 否定逆序环视 右边不是Y hi(?!d)能匹配到high
原文地址:https://www.cnblogs.com/ysit/p/13179515.html