正则表达式
简介
正则表达式(英语:Regular Expression,在代码中常简写为regex、regexp或RE),又称正规表示式、正规表示法、正规表达式、规则表达式、常规表示法,是计算机科学的一个概念。正则表达式使用单个字符串来描述、匹配一系列匹配某个句法规则的字符串。在很多文本编辑器里,正则表达式通常被用来检索、替换那些匹配某个模式的文本。
正则表达式规则,单字符匹配
字符
功能
正则表达式示例
符合匹配示例
.
匹配任意一个字符(除了n)
b.b
bab,b2b
[ ]
匹配来自[]中字符集的任意一个字符
i [abCde]m
i am
\d
匹配任何十进制数字,与[0-9]一致
w\dcschool
w3cschool
\D
匹配非数字,即不是数字
mou\Dh
mouth
\s
匹配任何空格字符,与[\n\t\r\v\f]相同
i\slike
i like
\S
匹配任何非空白字符,与\s相反
n\Se
noe,n3e
\w
匹配任何字母数字字符,与[A-Za-z0-9_]相同
[A-Za-z]w+
\W
匹配非单词字符
[0-9]\W[A-Z]
3 A
表示数量匹配
字符
功能
正则表达式示例
符合匹配的示例
*
匹配0次或者多次前面出现的正则表达式,即可有可无
a*
aaa
+
匹配前一个字符出现1次或者无限次,即至少有一次
a+
aaa
?
匹配前一个字符出现1次或者0次,要么有一次,要么没有
a?
a或者b
{m}
匹配前一个字符出现m次
[0-9]{5}
12345
{m.}
匹配前一个字符至少出现m次
a{5.}
aaaaa
{m,n}
匹配前一个字符出现从m到n次
a{2,6}
aaa
表示边界匹配
字符
功能
正则表达式示例
^
匹配字符串起始部分
^Dear
$
匹配字符串终止部分
fi$
b
匹配任何单词的边界
\bThe\b
B
匹配非单词边界
.*\Bver\
匹配分组
字符
功能
\
匹配左右任意一个表达式
(ab)
将括号中字符作为一个分组
\num
引用分组num匹配到的字符串
(?P)
分组起别名
(?P=name)
引用别名为name分组匹配到的字符串
re模块
在python中,可以使用内置的re模块来使用正则表达式
re模块常见的函数和方法
核心函数
说明
compile(pattern,flags=0)
使用任何可选的标记来编译正则表达式的模式,然后返回一个正则表达式对象
re模块函数和正则表达式对象方法
说明
match(pattern,string,flags=0)
尝试使用带有可选的标记的正则表达式的模式来匹配字符串。如果匹配成功,就返回匹配对象; 如果失败,就返回 None
search(pattern,string,flags=0)
使用可选标记搜索字符串中第一次出现的正则表达式模式。 如果匹配成功,则返回匹配对象; 如果失败,则返回 None
findall(pattern,string[,flags])
查找字符串中所有出现的正则表达式,并返回一个列表
finditer(pattern,string[,flags])
与findall相同,但返回的是一个迭代器而不是一个列表(不常用)
split(pattern,string,max=0)
根据正则表达式的模式分隔符,spilt函数将字符串分割为列表,然后返回成功匹配的列表,分割最多操作max次(默认分割所有匹配成功的位置)
sub(pattern,repl,string,count=0)
使用repl替换所有正则表达式的模式在字符串中出现的位置,除非定义count,否则就将替换所有出现的位置
常用的匹配对象方法
说明
group(num=0)
默认返回整个匹配对象或者返回编号为num的特定子组
groups(default=None)
返回一个包含所有匹配子组的元组,如果没有成功匹配,返回一个空元组
span()
常用的模块属性,大多数用于对正则表达式函数的修饰
说明
re.I
使匹配对大小写不敏感(忽略大小写)
re.S
.(点号)匹配除了n之外的所有字符,re.S标记表示.(点号)能够匹配全部字符
re.M
多行匹配,影响^和$
re.U
根据Unicode字符集解析字符。影响\w,\W,\b和\B
re.X
该标志通过给予你更灵活的格式以便你讲正则表达式写得更易于理解
re模块一般的使用方法
使用 compile() 函数将正则表达式的字符串形式编译为一个正则表达式对象;
通过正则表达式对象提供的一系列方法(如:match())对文本进行匹配查找,获得匹配结果,一个Match对象;
最后使用Match对象提供的属性和方法(例如:group())获得信息,根据需要进行其他的操作。
re模块使用示例
导入模块
import re
compile()函数
compile 函数用于编译正则表达式,生成一个 Pattern 对象,它的一般使用形式如下:
import re
# 将正则表达式编译成pattern对象
pattern = re.compile(r'\d+')
编译成正则表达式对象后,就可以使用上面所说的正则表达式对象方法了。
match()方法
match 方法用于查找字符串的头部(也可以指定起始位置),它是一次匹配,只要找到了一个匹配的结果就返回,而不是查找所有匹配的结果。它的一般使用形式如下:
match(string[, pos[, endpos]])
其中,string是待匹配的字符串,pos 和 endpos 是可选参数,指定字符串的起始和终点位置,默认值分别是 0 和 len (字符串长度)。因此,当你不指定 pos 和 endpos 时,match 方法默认匹配字符串的头部。
当匹配成功时,返回一个 Match 对象,如果没有匹配上,则返回 None。
>>> import re
>>>
>>> pattern = re.compile(r'\d+') # 正则表达式表示匹配至少一个数字
>>>
>>> m = pattern.match("one2three4") # match默认从开头开始匹配,开头是字母o,所以没有匹配成功
>>> print(m) # 匹配失败返回None
None
>>>
>>> m = pattern.match("1two3four") # 开头字符是数字,匹配成功
>>> print(m)
<_sre.SRE_Match object; span=(0, 1), match='1'>
>>>
>>> m.group() # group()方法获取匹配成功的字符
'1'
>>> m = pattern.match("onetwo3four56",6,12) # 指定match从数字3开始查找,第一个是数字3,匹配成功
>>> print(m)
<_sre.SRE_Match object; span=(6, 7), match='3'>
>>> m.group()
'3'
search()方法
search 方法用于查找字符串的任何位置,从任何位置开始往后查找,它也是一次匹配,只要找到了一个匹配的结果就返回,而不是查找所有匹配的结果,它的一般使用形式如下:
search(string[, pos[, endpos]])
其中,string 是待匹配的字符串,pos 和 endpos 是可选参数,指定字符串的起始和终点位置,默认值分别是 0 和 len (字符串长度)。
当匹配成功时,返回一个 Match 对象,如果没有匹配上,则返回 None。
In [1]: import re
In [2]: pattern = re.compile(r'[A-Za-z]+') # 表示匹配至少一个字母
In [3]: ret = pattern.search("123four5") # 这里如果使用match则不匹配,因为以数字开头
In [4]: print(ret)
<_sre.SRE_Match object; span=(3, 7), match='four'>
In [5]: ret.group()
Out[5]: 'four'
In [9]: ret = pattern.search("123four5six789",7,12)
In [10]: print(ret)
<_sre.SRE_Match object; span=(8, 11), match='six'>
In [11]: ret.group()
Out[11]: 'six'
In [12]: ret = pattern.search("123four5six789",1,2)
In [13]: print(ret) # 不匹配,返回None
None
findall()方法
match方法和search方法都是匹配到正则表达式的第一个内容,如果想要获取正则表达式匹配的所有内容,就可以使用findall方法了。这个方法会搜索整个字符串,然后返回匹配正则表达式的所有内容。
findall 方法的使用形式如下:
findall(string[, pos[, endpos]])
其中,string 是待匹配的字符串,pos 和 endpos 是可选参数,指定字符串的起始和终点位置,默认值分别是 0 和 len (字符串长度)。
findall 以列表形式返回全部能匹配的子串,如果没有匹配,则返回一个空列表。
示例:
import re
pattern = re.compile(r'\d+')
ret1 = pattern.findall("hello 123 world 456")# 匹配123,456
ret2 = pattern.findall("one1two2three3") # 匹配1,2,3
ret3 = pattern.findall("hello world") # 没有数字不匹配,返回空列表
print(ret1)
print(ret2)
print(ret3)
运行结果:
['123', '456']
['1', '2', '3']
[]
spilt()方法
split 方法按照能够匹配的子串将字符串分割后返回列表,它的使用形式如下:
split(string[, maxsplit])
其中,maxsplit 用于指定最大分割次数,不指定将全部分割。
示例:
>>> import re
>>>
>>> pattern = re.compile(r'[\s\;\,]+')
>>> ret = pattern.split("hello world;;ha,ha")
>>> print(ret)
['hello', 'world', 'ha', 'ha']
sub()方法
sub 方法用于替换,在python爬虫中常用语修改文本。比如把一串文本中所有数字去掉,把数字去掉可以使用字符串方法中的replace方法,但是太麻烦了,使用sub()方法就可以很方便去掉。sub()方法的使用形式如下:
sub(repl, string[, count])
其中,repl 可以是字符串也可以是一个函数:
如果 repl 是字符串,则会使用 repl 去替换字符串每一个匹配的子串,并返回替换后的字符串,另外,repl 还可以使用 id 的形式来引用分组,但不能使用编号 0;
如果 repl 是函数,这个方法应当只接受一个参数(Match 对象),并返回一个字符串用于替换(返回的字符串中不能再引用分组)。
count 用于指定最多替换次数,不指定时全部替换。
示例:
import re
content = '42hjad24ta d25a14aad'
content = re.sub('\d+','',content)
print(content)
运行结果:
hjadta daaad
正则表达式规则常见使用
贪婪匹配和非贪婪匹配
贪婪模式:在整个表达式匹配成功的前提下,尽可能多的匹配 ( * );
非贪婪模式:在整个表达式匹配成功的前提下,尽可能少的匹配 ( ? );
Python中默认是贪婪模式
示例
源字符串:abccc
贪婪模式匹配:abc*
非贪婪模式匹配:abc*?
abc*,匹配尽可能多个c
abc*?,匹配尽可能少个c,最少为0即没有,所以打印ab
>>> import re
>>>
>>> ret = re.match('abc*',"abccc")
>>> print(ret)
<_sre.SRE_Match object; span=(0, 5), match='abccc'>
>>>
>>> ret.group()
'abccc'
>>>
>>> ret = re.match('abc*?',"abccc")
>>> ret.group()
'ab'
分组
圆括号()匹配封闭的正则表达式,然后另存为子组。
>>> m = re.match('(\w\w\w)@(\d\d\d)\.(\w\w\w)',"[email protected]")
>>> m.group()
>>> m.group(1)
'xxx'
>>> m.group(2)
'163'
>>> m.group(3)
'com'
>>> m.groups()
('xxx', '163', 'com')
group()通常用于以普通方式显示所有的匹配部分,但也可以用于获取各个匹配的子组。而groups()方法可以获取一个包含所有匹配子字符串的元组。
转义匹配
当匹配目标中有正则表达式的特殊字符,就需要使用转义字符""将特殊字符的作用屏蔽掉。
>>> content = "(hello,world)"
>>> m = re.match('\(.*\)',content)
>>> print(m)
<_sre.SRE_Match object; span=(0, 13), match='(hello,world)'>
>>> m.group()
'(hello,world)'
通用匹配
.(点号)表示匹配任意一个字符,*(星号)表示匹配前面的字符无限次,组合起来.*就是匹配任意字符。
>>> content = "hello 123456789 world hahaha"
>>> m = re.match('^hello.*ha$',content)
>>> print(m)
<_sre.SRE_Match object; span=(0, 28), match='hello 123456789 world hahaha'>
>>> m.group()
'hello 123456789 world hahaha'
匹配多个字符串
竖线"|"表示匹配竖线左边的表达式或者右边的表达式,如re1|re2,满足其中一个表达式就匹配成功
>>> m = re.match('abc|adc|aec',"adc")
>>> m.group()
'adc'
>>> m = re.match('abc|adc|aec',"aoc")
>>> print(m)
None
>>> m = re.findall('abc|adc|aec',"abc aec aoc")
>>> print(m)
['abc', 'aec']
[]字符集使用
方括号[]表示匹配来自字符集中任意一个字符。
>>> m = re.match('[abc][123][A-Z]',"b2A")
>>> m.group()
'b2A'
>>> m = re.match('[abc][123][A-Z]',"a3A")
>>> m.group()
'a3A'
>>> m = re.match('[abc][123][A-Z]',"d2B") # 不匹配
>>> print(m)
None
>>>