Regular Expression

正则表达式的规则

常用元字符

代码 说明
. 匹配除换行符以外的任意字符
\w 匹配字母或数字或下划线
\s 匹配任意的空白符
\d 匹配数字
\b 匹配单词的开始或结束
^ 匹配字符串的开始
$ 匹配字符串的结束

常用限定符

代码/语法 说明
* 重复零次或更多次
+ 重复一次或更多次
? 重复零次或一次
{n} 重复n次
{n,} 重复n次或更多次
{n,m} 重复n到m次

常用反义词

代码/语法 说明
\W 匹配任意不是字母,数字,下划线,汉字的字符
\S 匹配任意不是空白符的字符
\D 匹配任意非数字的字符
\B 匹配不是单词开头或结束的位置
[^x] 匹配除了x以外的任意字符
[^aeiou] 匹配除了aeiou这几个字母以外的任意字符

预定义字符集表

\d \d匹配任何十进制数,它相当于类[0-9],\d+如果需要匹配一位或者多位数的数字时用
\D \D匹配任何非数字字符,它相当于类[^0-9]
\s \s匹配任何空白字符,它相当于类[\t\n\r\f\v]
\S \S匹配任何非空白字符,它相当于类[^\t\n\r\f\v]
\w \w匹配包括下划线在内任何字母数字字符,它相当于类 {a-z,A-Z,0-9,_}
\W \W匹配非任何字母数字字符包括下划线在内,它相当于类 { ^a-z,A-Z,0-9,_}
\A 仅匹配字符串开头,同^
\Z 仅匹配字符串结尾,同$
\b b匹配一个单词边界,也就是指单词和空格间的位置
\B [^\b]

常用正则表达式

引用:史上最全常用正则表达式大全

一、校验数字的表达式

  1. 数字:^[0-9]*$

  2. n位的数字:^\d{n}$

  3. 至少n位的数字:^\d{n,}$

  4. m-n位的数字:^\d{m,n}$

  5. 零和非零开头的数字:^(0|[1-9][0-9]*)$

  6. 非零开头的最多带两位小数的数字:^([1-9][0-9]*)+(.[0-9]{1,2})?$

  7. 带1-2位小数的正数或负数:^(\-)?\d+(\.\d{1,2})?$

  8. 正数、负数、和小数:^(\-|\+)?\d+(\.\d+)?$

  9. 有两位小数的正实数:^[0-9]+(.[0-9]{2})?$

  10. 有1~3位小数的正实数:^[0-9]+(.[0-9]{1,3})?$

  11. 非零的正整数:^[1-9]\d*$^([1-9][0-9]*){1,3}$^\+?[1-9][0-9]*$

  12. 非零的负整数:^\-[1-9][]0-9"*$^-[1-9]\d*$

  13. 非负整数:^\d+$^[1-9]\d*|0$

  14. 非正整数:^-[1-9]\d*|0$^((-\d+)|(0+))$

  15. 非负浮点数:^\d+(\.\d+)?$^[1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0$

  16. 非正浮点数:^((-\d+(\.\d+)?)|(0+(\.0+)?))$^(-([1-9]\d*\.\d*|0\.\d*[1-9]\d*))|0?\.0+|0$

  17. 正浮点数:^[1-9]\d*\.\d*|0\.\d*[1-9]\d*$^(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$

  18. 负浮点数:^-([1-9]\d*\.\d*|0\.\d*[1-9]\d*)$^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$

  19. 浮点数:^(-?\d+)(\.\d+)?$^-?([1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0)$

二、校验字符的表达式

  1. 汉字:^[\u4e00-\u9fa5]{0,}$

  2. 英文和数字:^[A-Za-z0-9]+$ 或 ^[A-Za-z0-9]{4,40}$

  3. 长度为3-20的所有字符:^.{3,20}$

  4. 由26个英文字母组成的字符串:^[A-Za-z]+$

  5. 由26个大写英文字母组成的字符串:^[A-Z]+$

  6. 由26个小写英文字母组成的字符串:^[a-z]+$

  7. 由数字和26个英文字母组成的字符串:^[A-Za-z0-9]+$

  8. 由数字、26个英文字母或者下划线组成的字符串:^\w+$ 或 ^\w{3,20}$

  9. 中文、英文、数字包括下划线:^[\u4E00-\u9FA5A-Za-z0-9_]+$

  10. 中文、英文、数字但不包括下划线等符号:^[\u4E00-\u9FA5A-Za-z0-9]+$ ^[\u4E00-\u9FA5A-Za-z0-9]{2,20}$

  11. 可以输入含有^%&',;=?$"等字符:[^%&',;=?$\x22]+ 12

  12. 禁止输入含有~的字符:[^~\x22]+

三、特殊需求表达式

  1. Email地址:^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$

  2. 域名:[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(/.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+/.?

  3. InternetURL:[a-zA-z]+://[^\s]*^http://([\w-]+\.)+[\w-]+(/[\w-./?%&=]*)?$

  4. 手机号码:^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\d{8}$

  5. 电话号码("XXX-XXXXXXX"、"XXXX-XXXXXXXX"、"XXX-XXXXXXX"、"XXX-XXXXXXXX"、"XXXXXXX"和"XXXXXXXX):^(\(\d{3,4}-)|\d{3.4}-)?\d{7,8}$

  6. 国内电话号码(0511-4405222、021-87888822):\d{3}-\d{8}|\d{4}-\d{7}

  7. 身份证号(15位、18位数字):^\d{15}|\d{18}$

  8. 短身份证号码(数字、字母x结尾):^([0-9]){7,18}(x|X)?$ ^\d{8,18}|[0-9x]{8,18}|[0-9X]{8,18}?$

  9. 帐号是否合法(字母开头,允许5-16字节,允许字母数字下划线):^[a-zA-Z][a-zA-Z0-9_]{4,15}$

  10. 密码(以字母开头,长度在6~18之间,只能包含字母、数字和下划线):^[a-zA-Z]\w{5,17}$

  11. 强密码(必须包含大小写字母和数字的组合,不能使用特殊字符,长度在8-10之间): ^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,10}$

  12. 日期格式:^\d{4}-\d{1,2}-\d{1,2}

  13. 一年的12个月(01~09和1~12):^(0?[1-9]|1[0-2])$

  14. 一个月的31天(01~09和1~31):^((0?[1-9])|((1|2)[0-9])|30|31)$

  15. 钱的输入格式:

有四种钱的表示形式我们可以接受:"10000.00" 和 "10,000.00", 和没有 "分" 的 "10000" 和 "10,000":^[1-9][0-9]*$

这表示任意一个不以0开头的数字,但是,这也意味着一个字符"0"不通过,所以我们采用下面的形式:^(0|[1-9][0-9]*)$

一个0或者一个不以0开头的数字.我们还可以允许开头有一个负号:^(0|-?[1-9][0-9]*)$

这表示一个0或者一个可能为负的开头不为0的数字.让用户以0开头好了.把负号的也去掉,因为钱总不能是负的吧.下面我们要加的是说明可能的小数部分:^[0-9]+(.[0-9]+)?$

必须说明的是,小数点后面至少应该有1位数,所以"10."是不通过的,但是 "10" 和 "10.2" 是通过的:^[0-9]+(.[0-9]{2})?$

这样我们规定小数点后面必须有两位,如果你认为太苛刻了,可以这样:^[0-9]+(.[0-9]{1,2})?$

这样就允许用户只写一位小数.下面我们该考虑数字中的逗号了,我们可以这样: ^[0-9]{1,3}(,[0-9]{3})*(.[0-9]{1,2})?$

到3个数字,后面跟着任意个 逗号+3个数字,逗号成为可选,而不是必须: ^([0-9]+|[0-9]{1,3}(,[0-9]{3})*)(.[0-9]{1,2})?$

备注:这就是最终结果了,别忘了"+"可以用"*"替代如果你觉得空字符串也可以接受的话(奇怪,为什么?)最后,别忘了在用函数时去掉去掉那个反斜杠,一般的错误都在这里

  1. xml文件:^([a-zA-Z]+-?)+[a-zA-Z0-9]+\\.[x|X][m|M][l|L]$

  2. 中文字符的正则表达式:[\u4e00-\u9fa5]

  3. 双字节字符:[^\x00-\xff] (包括汉字在内,可以用来计算字符串的长度(一个双字节字符长度计2,ASCII字符计1))

  4. 空白行的正则表达式:\n\s*\r (可以用来删除空白行)*

  5. HTML标记的正则表达式:<(\S*?)[^>]*>.*?</\1>|<.*? /> (网上流传的版本太糟糕,上面这个也仅仅能部分,对于复杂的嵌套标记依旧无能为力)

  6. 首尾空白字符的正则表达式: ^\s*|\s*$(^\s*)|(\s*$) (可以用来删除行首行尾的空白字符(包括空格、制表符、换页符等等),非常有用的表达式)

  7. 腾讯QQ号:[1-9][0-9]{4,} (腾讯QQ号从10000开始)

  8. 中国邮政编码:[1-9]\d{5}(?!\d) (中国邮政编码为6位数字)

  9. IP地址:\d+\.\d+\.\d+\.\d+ (提取IP地址时有用)

  10. IP地址:((?:(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d)\\.){3}(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d))

Python re模块

人生苦短,不如Python。

引用:python基础—re模块—正则表达式

python从1.5版本起增加re模块为自带的模块,提供了Perl风格的正则表达式模式

以下是python re库的常用函数

函数 描述
compile(pattern[, flags]) 根据包含正则表达式的字符串创建模式对象
search(pattern, string[, flags]) 在字符串中查找模式
match(pattern, string[, flags]) 在字符串开头匹配模式
split(pattern, string[, maxsplit=0]) 根据模式来分割字符串
findall(pattern, string) 返回一个列表,其中包含字符串中所有与模式匹配的子串
sub(pat, repl, string[, count=0]) 将字符串中与模式pat匹配的子串都替换为repl
escape(string) 对字符串中所有的正则表达式特殊字符都进行转义
  • re.compile()

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
compile 函数用于编译正则表达式,生成一个正则表达式( Pattern )对象,供 match()  search() 这两个函数使用。

语法格式为:

re.compile(pattern[, flags])

实例

>>>import re

>>> pattern = re.compile(r'\d+') # 用于匹配至少一个数字

>>> m = pattern.match('one12twothree34four') # 查找头部,没有匹配

>>> print(m)

None

>>> m = pattern.match('one12twothree34four', 2, 10) # 从'e'的位置开始匹配,没有匹配

>>> print(m)

None

>>> m = pattern.match('one12twothree34four', 3, 10) # 从'1'的位置开始匹配,正好匹配 >>>

print(m) # 返回一个 Match 对象
<_sre.SRE_Match object at 0x10a42aac0>

>>> m.group(0) # 可省略 0 '12'

>>> m.start(0) # 可省略 0 3

>>> m.end(0) # 可省略 0 5

>>> m.span(0) # 可省略 0 (3, 5)

在上面,当匹配成功时返回一个 Match 对象,其中:

group([group1, ]) 方法用于获得一个或多个分组匹配的字符串,当要获得整个匹配的子串时,可直接使用 group()  group(0)
start([group]) 方法用于获取分组匹配的子串在整个字符串中的起始位置(子串第一个字符的索引),参数默认值为 0
end([group]) 方法用于获取分组匹配的子串在整个字符串中的结束位置(子串最后一个字符的索引+1),参数默认值为 0
span([group]) 方法返回 (start(group), end(group))
再看看一个例子:

实例

>>>import re

>>> pattern = re.compile(r'([a-z]+) ([a-z]+)', re.I) # re.I 表示忽略大小写

>>> m = pattern.match('Hello World Wide Web')

>>> print(m)# 匹配成功,返回一个 Match 对象
<_sre.SRE_Match object at 0x10bea83e8>

>>> m.group(0) # 返回匹配成功的整个子串 'Hello World'

>>> m.span(0) # 返回匹配成功的整个子串的索引 (0, 11)

>>> m.group(1) # 返回第一个分组匹配成功的子串 'Hello'

>>> m.span(1) # 返回第一个分组匹配成功的子串的索引 (0, 5)

>>> m.group(2) # 返回第二个分组匹配成功的子串 'World'

>>> m.span(2) # 返回第二个分组匹配成功的子串 (6, 11)

>>> m.groups() # 等价于 (m.group(1), m.group(2), ...) ('Hello', 'World')

>>> m.group(3) # 不存在第三个分组

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: no such group

  • re.search()&re.match()

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
re.search 扫描整个字符串并返回第一个成功的匹配。

函数语法:

re.search(pattern, string, flags=0)

函数参数说明:

pattern:匹配的正则表达式
string:要匹配的字符串。
flags:标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。

    
匹配成功re.search方法返回一个匹配的对象,否则返回None

我们可以使用group(num)  groups() 匹配对象函数来获取匹配表达式。

匹配对象方法

group(num=0):匹配的整个表达式的字符串,group() 可以一次输入多个组号,在这种情况下它将返回一个包含那些组所对应值的元组。
groups():返回一个包含所有小组字符串的元组,从 1  所含的小组号。

实例

import re

line = "Cats are smarter than dogs";
searchObj = re.search( r'(.*) are (.*?) .*', line, re.M|re.I)

if searchObj:
      print ("searchObj.group() : ", searchObj.group())
      print ("searchObj.group(1) : ", searchObj.group(1))
      print ("searchObj.group(2) : ", searchObj.group(2))
else:
      print( "Nothing found!!")

以上实例执行结果如下:

searchObj.group() : Cats are smarter than dogs
searchObj.group(1) : Cats
searchObj.group(2) : smarter

 
_____________________________________________________________________________


re.match 尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none

函数语法:

re.match(pattern, string, flags=0)

函数参数说明:(同re.search一样

匹配成功re.match方法返回一个匹配的对象,否则返回None

我们可以使用group(num)  groups() 匹配对象函数来获取匹配表达式。

匹配对象方法:(同re.search一样

实例

import re

print(re.match('www', 'www.runoob.com').span()) # 在起始位置匹配
print(re.match('com', 'www.runoob.com')) # 不在起始位置匹配

以上实例运行输出结果为:
(0, 3) 
None

实例

import re

line = "Cats are smarter than dogs"
matchObj = re.match( r'(.*) are (.*?) .*', line, re.M|re.I)

if matchObj:
     print("matchObj.group() : ", matchObj.group())
     print("matchObj.group(1) : ", matchObj.group(1))
     print("matchObj.group(2) : ", matchObj.group(2))
else:
     print("No match!!")

以上实例执行结果如下:

matchObj.group() : Cats are smarter than dogs
matchObj.group(1) : Cats
matchObj.group(2) : smarter

 
____________________________________________________________________________


re.match与re.search的区别:
re.match只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None;而re.search匹配整个字符串,直到找到一个匹配。

实例

import re
line = "Cats are smarter than dogs";
matchObj = re.match( r'dogs', line, re.M|re.I)
if matchObj:
     print("match --> matchObj.group() : ", matchObj.group())
else:
     print ("No match!!")
matchObj = re.search( r'dogs', line, re.M|re.I)
if matchObj:
     print("search --> matchObj.group() : ", matchObj.group())
else:
     print("No match!!")

以上实例运行结果如下:

No match!!
search --> matchObj.group() : dogs

  • re.split()

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
split 方法按照能够匹配的子串将字符串分割后返回列表,它的使用形式如下:

re.split(pattern, string[, maxsplit=0, flags=0])

参数:
pattern:匹配的正则表达式
string:要匹配的字符串。
maxsplit:分隔次数,maxsplit=1 分隔一次,默认为 0,不限制次数。
flags:标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。

实例

>>>import re

>>> re.split('\W+', 'runoob, runoob, runoob.')
['runoob', 'runoob', 'runoob', '']

>>> re.split('(\W+)', ' runoob, runoob, runoob.')
['', ' ', 'runoob', ', ', 'runoob', ', ', 'runoob', '.', '']

>>> re.split('\W+', ' runoob, runoob, runoob.', 1)
['', 'runoob, runoob, runoob.']

>>> re.split('a*', 'hello world') # 对于一个找不到匹配的字符串而言,split 不会对其作出分割
['hello world']

  • re.sub()

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
Python  re 模块提供了re.sub用于替换字符串中的匹配项

语法:
re.sub(pattern, repl, string, count=0, flags=0)

参数:
pattern : 正则中的模式字符串。
repl : 替换的字符串,也可为一个函数。
string : 要被查找替换的原始字符串。
count : 模式匹配后替换的最大次数,默认 0 表示替换所有的匹配。

    
实例:

import re

phone = "2004-959-559 # 这是一个国外电话号码"
num = re.sub(r'#.*$', "", phone)   # 删除字符串中的 Python注释
print ("电话号码是: ", num)
num = re.sub(r'\D', "", phone) # 删除非数字(-)的字符串
print ("电话号码是 : ", num)

以上实例执行结果如下:

电话号码是: 2004-959-559
电话号码是 : 2004959559

 

以下实例中将字符串中的匹配的数字乘以 2

import re

def double(matched):   # 将匹配的数字乘以 2
    value = int(matched.group('value'))
    return str(value * 2)

s = 'A23G4HFD567'
print(re.sub('(?P<value>\d+)', double, s))

执行输出结果为:
A46G8HFD1134

  • findall()

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果没有找到匹配的,则返回空列表。

注意: match  search 是匹配一次,findall 匹配所有。

语法格式为:

findall(string[, pos[, endpos]])

参数:

string: 待匹配的字符串。
pos: 可选参数,指定字符串的起始位置,默认为 0
endpos: 可选参数,指定字符串的结束位置,默认为字符串的长度。
查找字符串中的所有数字:

实例

import re

pattern = re.compile(r'\d+') # 查找数字
result1 = pattern.findall('runoob 123 google 456')
result2 = pattern.findall('run88oob123google456', 0, 10) #取字符串之中0-10之间的数字出来
print(result1result2)

输出结果:
['123', '456']['88', '12']

  • re.finditer()

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
 findall 类似,在字符串中找到正则表达式所匹配的所有子串,并把它们作为一个迭代器返回。

re.finditer(pattern, string, flags=0)

参数:

pattern:匹配的正则表达式
string:要匹配的字符串。
flags:标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。

实例

import re

it = re.finditer(r"\d+","12a32bc43jf3")
for match in it:
    print (match.group() )

输出结果:
12 32 43 3

  • re.escape()

re.escape()的主要作用就是将一个字符串变成可以匹配的正则表达式

1
2
3
4
5
6
re.escape是一个工具函数,用于对字符串中所有可能被视为正则表达式运算符的字符进行转义。使用这个函数的情况有:字符串很长,其中包含大量特殊字符,而你不想输入大量的反斜杠;你从用户那里获取了一个字符串(例如,通过函数input),想将其用于正则表达式中。下面的示例说明了这个函数的工作原理:
>>> re.escape('www.python.org') 
'www\\.python\\.org' 
>>> re.escape('But where is the ambiguity?') 
'But\\ where\\ is\\ the\\ ambiuity\\?' 

updatedupdated2021-11-212021-11-21