正则表达式
正则表达式是一个特殊的字符序列,它能帮助你方便的检查一个字符串是否与某种模式匹配。
Python 自1.5版本起增加了re 模块,它提供 Perl 风格的正则表达式模式。
re 模块使 Python 语言拥有全部的正则表达式功能。
compile 函数根据一个模式字符串和可选的标志参数生成一个正则表达式对象。该对象拥有一系列方法用于正则表达式匹配和替换。
re 模块也提供了与这些方法功能完全一致的函数,这些函数使用一个模式字符串做为它们的第一个参数。
re模块
re模块是python中处理正则表达式的一个模块,通过re模块的方法,把正则表达式pattern编译成正则对象,以便使用正则对象的方法;
re.findall()
在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果没有找到匹配的,则返回空列表。
注意: match 和 search 是匹配一次 findall 匹配所有。
语法格式为:
findall(string[, pos[, endpos]])
参数:
- string : 待匹配的字符串。
- pos : 可选参数,指定字符串的起始位置,默认为 0。
- endpos : 可选参数,指定字符串的结束位置,默认为字符串的长度。
举例:
import re
ret = re.findall('w\w{3}d','hello world') #匹配以w开始中间有三个字符并且以d结尾的;
print(ret)
#打印结果['world']
ret = re.findall('hello','123hkhsfhelloworldjl') #匹配hello;
print(ret)
#打印结果['hello']
ret = re.findall('abc','111abc222ABC333abc')
print(ret)
#['abc', 'abc']
re.match()
re.match 尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none。
函数语法:
re.match(pattern, string, flags=0)
参数说明:
参数 | 描述 |
---|---|
pattern | 匹配的正则表达式 |
string | 要匹配的字符串。 |
flags | 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。 |
使用group(num) 或 groups() 匹配对象函数来获取匹配表达式;
匹配对象方法 | 描述 |
---|---|
group(num=0) | 匹配的整个表达式的字符串,group() 可以一次输入多个组号,在这种情况下它将返回一个包含那些组所对应值的元组。 |
groups() | 返回一个包含所有小组字符串的元组,从 1 到 所含的小组号。 |
举例:
ret = re.match('abc','abcjhabciyu')
print(ret)
print(ret.group())
print(ret.span())
#输出结果:
#<re.Match object; span=(0, 3), match='abc'>
#abc
#(0, 3)
re.search()
re.search 扫描整个字符串并返回第一个成功的匹配。
函数语法:
re.search(pattern, string, flags=0)
举例:
ret = re.search('abc','12habcjhabcjlk')
print(ret)
print(ret.group())
print(ret.span())
#<re.Match object; span=(3, 6), match='abc'>
#abc
#(3, 6)
re.match与re.search的区别
re.match只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None;而re.search匹配整个字符串,直到找到一个匹配。
检索和替换
Python 的 re 模块提供了re.sub用于替换字符串中的匹配项。
使用语法:
re.sub(pattern, repl, string, count=0, flags=0)
参数:
- pattern : 正则中的模式字符串。
- repl : 替换的字符串,也可为一个函数。
- string : 要被查找替换的原始字符串。
- count : 模式匹配后替换的最大次数,默认 0 表示替换所有的匹配。
举例(将abc替换为ABCEDFG):
ret = re.sub('abc','ABCDEFG','111abc000')
print(ret)
#111ABCDEFG000
re.compile 函数
compile 函数用于编译正则表达式,生成一个正则表达式( Pattern )对象。
语法格式:
re.compile(pattern[, flags])
参数:
-
pattern : 一个字符串形式的正则表达式
-
flags : 可选,表示匹配模式,比如忽略大小写,多行模式等,具体参数为:
- re.I 忽略大小写
- re.L 表示特殊字符集 \w, \W, \b, \B, \s, \S 依赖于当前环境
- re.M 多行模式
- re.S 即为 . 并且包括换行符在内的任意字符(. 不包括换行符)
- re.U 表示特殊字符集 \w, \W, \b, \B, \d, \D, \s, \S 依赖于 Unicode 字符属性数据库
- re.X 为了增加可读性,忽略空格和 # 后面的注释
举例(查找.com):
obj = re.compile('\.com')
ret = obj.findall('www.baidu.com')
print(ret)
#['.com']
re.split
split 方法按照能够匹配的子串将字符串分割后返回列表;
使用方法:
re.split(pattern, string[, maxsplit=0, flags=0])
参数:
参数 | 描述 |
---|---|
pattern | 匹配的正则表达式 |
string | 要匹配的字符串。 |
maxsplit | 分隔次数,maxsplit=1 分隔一次,默认为 0,不限制次数。 |
flags | 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。 |
举例:
ret = re.split('s','11s22s33')
print(ret) #打印结果:['11', '22', '33']
sd = re.split('[s,d]','s3s3d4d7s8s7d7d8')
print(sd)
#打印结果['', '3', '3', '4', '7', '8', '7', '7', '8']
正则表达式表达模式
模式字符串使用特殊的语法来表示一个正则表达式:
字母和数字表示他们自身。一个正则表达式模式中的字母和数字匹配同样的字符串。
多数字母和数字前加一个反斜杠时会拥有不同的含义。
标点符号只有被转义时才匹配自身,否则它们表示特殊的含义。
反斜杠本身需要使用反斜杠转义。
由于正则表达式通常都包含反斜杠,所以你最好使用原始字符串来表示它们。模式元素(如 r'\t',等价于 '\\t')匹配相应的特殊字符。
下表列出了正则表达式模式语法中的特殊元素。如果你使用模式的同时提供了可选的标志参数,某些模式元素的含义会改变。
特殊符号和字符
元字符指正则表达式中的特殊符号和字符。
符号:
符号 | 描述 | 示例 |
---|---|---|
. | 通配符:匹配任何字符(除\n 之外) | f.o |
^ | 匹配字符串起始部分 | ^foo |
$ | 匹配字符串终止部分 | bar$ |
* | 匹配0次或者多次前面出现的正则表达式 | [A-Za-z0-9]* |
+ | 匹配1次或者多次前面出现的正则表达式 | [a-z]+\\.com |
? | 匹配0次或者1次前面出现的正则表达式 | goo? |
{N} | 匹配N次前面出现的正则表达式 | [0-9]{3} |
{M,N} | 匹配M~N次前面出现的正则表达式 | [0-9]{5,9} |
[…] | 匹配来自字符集的任意单一字符 | [aeiou] |
[x-y] | 匹配x~y范围中的任意单一字符 | [0-9], [A-Za-z] |
[^…] | 不匹配此字符集中出现的任何一个字符, 包括某一范围的字符 | [^aeiou], \[^A-Za-z] |
(…) | 匹配圆括号中的正则表达式,或者指定一个子组的开始和结束位置 | `([0-9]{3})? |
| | A | B,表示匹配正则表达式 A 或者 B | |
\ | 下边列举了由字符 '\' 和另一个字符组成的特殊含义。注意,'\' + 元字符的组合可以解除元字符的特殊功能 |
1、匹配任何字符(.);
ret = re.findall('t..t','123test00test')
print(ret)
#['test', 'test']
2、匹配以什么开头的字符(^);
ret = re.findall('^hello','hello1234hello')
print(ret)
#['hello']
3、匹配以什么结尾的字符($);
ret = re.findall('te.t$','test666teat')
print(ret)
#['teat']
4、重复匹配(*);
ret = re.findall('us.*','abcde00userus123')
print(ret) #['userus123']
tes = re.findall('ab*','abab123abab')
print(tes) #['ab', 'ab', 'ab', 'ab']
5、匹配1次或者多次前面出现的正则表达式(+);
ret = re.findall('ax+','1axxxxxx00aa0aaaxx')
print(ret)
#['axxxxxx', 'axx']
6、匹配0次或者1次前面出现的正则表达式;
ret = re.findall('a?c','aaacc00acc00aabc00aac')
print(ret)
#['ac', 'c', 'ac', 'c', 'c', 'ac']
7、匹配N此前面出现的正则表达式{};
ret = re.findall('a{3}','1aaababaacbaa')
print(ret) #匹配3个a['aaa']
tes = re.findall('a{1,3}','a0aa0aaa0aaaa')
print(tes) #1-3个a都会匹配上['a', 'aa', 'aaa', 'aaa', 'a']
8、匹配圆括号中的正则表达式,或者指定一个子组的开始和结束位置();
ret = re.search('(as)+','asasjkh12asas')
print(ret) #<re.Match object; span=(0, 4), match='asas'>
print(ret.group()) #asas
9、匹配A或者B(|);
ret = re.search('(as)|3','as3').group()
print(ret) #as
tes = re.search('(as)|3','3as').group()
print(tes) #3
结论:*等价于{0,正无穷}、+等价于{1,正无穷}、?等价于{0,1}
创建字符集
使用[]
创建字符集,可以匹配某些特定字符。
正则表达式 | 匹配的字符串 |
---|---|
b[aeiu]t | bat,bet,bit,but |
[cr][23] | c2,c3,r2,r3 |
限定范围和否定
除了单字符外,字符集还支持匹配指定的字符范围。两个字符中间用连字符 -
连接,用于指定一个字符的范围。如果^
紧跟在左括号后面,这个符号就表示不匹配给定字符集中任何一个字符。
正则表达式 | 匹配的字符串 |
---|---|
z.[0-9] | z 后面跟着任何一个字符,然后跟着一个数字 |
[r-u][env-y][us] | 等价于[rstu][envwxy][us] ,比如匹配res |
[^aeiou] | 匹配一个非元音字符 |
[^\t\n] | 不匹配制表符或换行符 |
使用闭包操作符实现存在性和频数匹配
符号 | 说明 |
---|---|
* | 匹配左侧的正则表达式出现零次或多次的情形,这称作Kleene 闭包 |
+ | 匹配一次或多次出现的正则表达式,这称作正闭包操作符 |
? | 操作符将匹配零次或者一次出现的正则表达式 |
{} | 里面或者是单值,或者是一对由逗号分隔的数值;{N} 表示匹配N 次;{N,M} 表示匹配N~M 次 |
如果问号紧跟在任何使用闭包操作符的匹配后面,它将直接要求正则表达式引擎匹配尽可能少的次数。当模式匹配使用分组操作符时,正则表达式引擎将试图吸收匹配该模式的尽可能多的字符,这通常叫做贪婪匹配。问号要求正则表达式引擎在当前正则表达式中尽可能少地匹配字符。
示例:
正则表达式 | 匹配的字符串 |
---|---|
[dn]ot | do,dot,no,not |
0?[1-9] | 可能存在前置0的数字 |
[0-9]{15,16} | 匹配15或者16个数字 |
</?[^>]+> | 匹配HTML标签 |
1、匹配来自字符集的任意单一字符[ ]
ret = re.findall('[abc]','123jhiuuw')
print(ret) #[]
tes = re.findall('[a-z]','00agbdABCDEFouo767')
print(tes) #['a', 'g', 'b', 'd', 'o', 'u', 'o']
ret = re.findall('[a,,]','abc.,')
print(ret) #打印结果['a', ',']
2、匹配所有数字和字母
ret = re.findall('[0-9a-zA-Z]','abc123XYZ')
print(ret)
#['a', 'b', 'c', '1', '2', '3', 'X', 'Y', 'Z']
3、^放在[ ]里表示取反
ret = re.findall('^ab','abcdefg123')
print(ret) #['ab']
se = re.findall('[^ab]','abc00abce')
print(se) #['c', '0', '0', 'c', 'e']
tes = re.findall('[^3,4]','abc0030aab4bc')
print(tes) #['a', 'b', 'c', '0', '0', '0', 'a', 'a', 'b', 'b', 'c']
特殊符号
实例 | 描述 |
---|---|
. | 匹配除 "\n" 之外的任何单个字符。要匹配包括 '\n' 在内的任何字符,请使用象 '[.\n]' 的模式。 |
\d | 匹配一个数字字符。等价于 [0-9]。 |
\D | 匹配一个非数字字符。等价于 [^0-9]。 |
\s | 匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。 |
\S | 匹配任何非空白字符。等价于 [^ \f\n\r\t\v]。 |
\w | 匹配包括下划线的任何字母数字字符。等价于'[A-Za-z0-9_]'。 |
\W | 匹配任何非字母数字字符。等价于 '[^A-Za-z0-9_]'。 |
\b | 匹配一个特殊字符的边界。 |
示例:
#\d,\D相反;匹配所有的数字
print(re.findall('\d','kajsh129364873'))
#['1', '2', '9', '3', '6', '4', '8', '7', '3']
#匹配两组11位的数字
print(re.findall('\d{11}','a187312461946708xhg817653256341'))
#['18731246194', '81765325634']
#\s,\S相反;匹配任何空白符
print(re.findall('\sabc','1ab,c abc123'))
#[' abc']
#\w,\W相反;匹配包括下划线的任何字母数字字符
print(re.findall('\w','awk 123 abc,e_fg'))
#['a', 'w', 'k', '1', '2', '3', 'a', 'b', 'c', 'e', '_', 'f', 'g']
#\d:匹配一个特殊字符的边界
print(re.findall(r'I\b','hello,I am a LIST'))
#['I']
print(re.findall(r'\bI','helloI am a LIST'))
#I的左边没有特殊字符,所以匹配为空[]
转义符(\)
1. 将一个普通字符变成特殊字符,例如 \d 表示匹配所有十进制数字
2. 解除元字符的特殊功能,例如 \. 表示匹配点号本身
3. 引用序号对应的子组所匹配的字符串
m = re.search(r'\bblow', 'blow').group()
print(m) #blow
ret = re.search('a\.','a.gj').group()
print(ret) #a.
ret = re.findall(r'\\cd','adhf\cd')
print(ret) #['\\cd']
使用圆括号指定分组
有时候不仅想要知道整个字符串是否匹配我们的标准,而且想要知道能否提取任何已经成功匹配的特定字符串或者子字符串,可以使用分组来实现。
一对圆括号可以实现一下任意一个功能:
- 对正则表达式进行分组
- 匹配子组
对正则表达式分组,可以在整个正则表达式中使用重复的操作符。
使用圆括号进行分组的一个副作用就是,匹配模式的子字符串可以保存起来供后续使用。这些子组能够被同一次的匹配或者搜索重复调用,或者提取出来用于后续处理。
匹配子组的重要性在于,很多时候除了进行匹配操作以外,我们还想要提取所匹配的模式。
示例:
正则表达式 | 匹配的字符串 |
---|---|
\d+(\.\d*)? | 表示简单浮点数的字符串 |
扩展表示法:
正则表达式的扩展表示法,以问号开始(?...)
。他们通常用于在判断匹配之前提供标记,实现一个前视或者后视匹配,或者条件检查,(?P<name>)
表示一个分组匹配;
示例:
ret = re.search('(?P<id>\d{3})/(?P<name>\w{3})','wekk123/abcd')
print(ret.group())
print(ret.group('id'))
print(ret.group('name'))
打印结果
123/abc
123
abc
参考:https://segmentfault.com/a/1190000015123481