正则表达式 Regular Expression
背景定义
每次临时用正则表达式,理解和学习的一知半解。干脆慢慢总结一下,以后更新。其中看到的很多相关教程都标识在reference中,文中部分内容直接来自参考教程,没有一一标注。非常感谢他们的总结。
自己对正则表达式的理解就是定义一个字符串的结构模式,在文本中去匹配符合该模式的字符串。使用match()、search()、findall()等常用方法去匹配,split()和sub()函数在匹配后做分割和替换,功能合二为一。然后可以通过match object函数得到匹配后的结果。
模式语言
如何去构造模式?用什么样的符号,以什么样的方式去构造模式?
例如,\d可以匹配一个数字;\w可以匹配一个字母或数字;.可以匹配任意字符;用*表示任意个字符(包括0个),用+表示至少一个字符,用?表示0个或1个字符,用{n}表示n个字符,用{n,m}表示n-m个字符。
- ‘00\d’可以匹配’007’,但无法匹配’00A’;
- ‘\d\d\d’可以匹配’010’;
- ‘\w\w\d’可以匹配’py3’;
- 'py.‘可以匹配’pyc’、‘pyo’、'py!'等等;
- \d{3}表示匹配3个数字,例如’010’;
- \d{3,8}表示3-8个数字,例如’1234567’。
匹配字符的操作符
操作符 | 含义 |
---|---|
. | 表示任何单个字符,除了换行符 当re.DOTALL标记被指定时,则可以匹配包括换行符的任意字符。 |
\w | 匹配字母数字及下划线 |
\W | 匹配非字母数字及下划线 |
\s | 匹配任意空白字符,等价于 [\t\n\r\f]. |
\S | 匹配任意非空字符 |
\d | 匹配任意数字,等价于 [0-9]. |
\D | 匹配任意非数字 |
\n | 匹配一个换行符 |
\t | 匹配一个制表符 |
匹配数量的操作符
操作符 | 含义 |
---|---|
* | 前一个字符0次或无限次扩展 abc*表示ab、abc、abcc、abccc等 |
+ | 前一个字符1次或无限次扩展 abc+表示abc、abcc、abccc等 |
? | 前一个字符0次或1次扩展 abc?表示ab、abc |
| | 左右表达式任意一个 abc|def表示abc或def |
{m} | 扩展前一个字符m次 ab{2}c表示abbc |
{m,n} | 扩展前一个字符m至n次(含n) ab{1,2}c表示abc、abbc |
匹配集合的操作符
操作符 | 含义 |
---|---|
[] | 字符集,对单个字符给出取值范围 [abc]表示a、b、c,[a-z]表示a到z单个字符 [0-9] 等价于\d [A-Za-z0-9_]等价于\w |
[^] | 非字符集,对单个字符给出排除范围 [^abc]表示非a或b或c的单个字符 |
() | 分组标记,内部只能使用|操作符 (abc)表示abc,(abc|def)表示abc、def |
匹配位置的操作符
操作符 | 含义 |
---|---|
^ | 匹配字符串开头 ^abc表示abc且在一个字符串的开头 |
$ | 匹配字符串结尾 abc$表示abc且在一个字符串的结尾 |
\A | 匹配字符串开始 |
\Z | 匹配字符串结束,如果是存在换行,只匹配到换行前的结束字符串。 |
\z | 匹配字符串结束 |
\G | 匹配最后匹配完成的位置。 |
\b | 匹配一个单词边界,也就是指单词和空格间的位置。 ‘er\b’ 可以匹配"never" 中的 ‘er’,但不能匹配 “verb” 中的 ‘er’。 |
\B | 匹配非单词边界。 ‘er\B’ 能匹配 “verb” 中的 ‘er’,但不能匹配 “never” 中的 ‘er’。 |
常用实例
Pattern | 含义 |
---|---|
[0-9] | 匹配任何数字。类似于 [0123456789] |
[a-z] | 匹配任何小写字母 |
[A-Z] | 匹配任何大写字母 |
[a-zA-Z0-9] | 匹配任何字母及数字 |
[^aeiou] | 除了aeiou字母以外的所有字符 |
[^0-9] | 匹配除了数字外的字符 |
^[A-Za-z]+$ | 由26个字母组成的字符串 |
^[A-Za-z0-9]+$ | 由26个字母和数字组成的字符串 |
^-?\d+$ | 整数形式的字符串 |
^[0-9]*[1-9][0-9]*$ | 正整数形式的字符串 |
[1-9]\d{5} | 中国境内邮政编码,6位 |
[\u4e00-\u9fa5] | 匹配中文字符 |
\d{3}-\d{8}|\d{4}-\d{7} | 国内电话号码,010-68913536或0558-1234567 |
常用函数
re 模块使 Python 语言拥有全部的正则表达式功能。
函数 — Functions | 功能 |
---|---|
re.search() | 在一个字符串中搜索匹配正则表达式的第一个位置,返回match对象(match object) |
re.match() | 从一个字符串的开始位置起匹配正则表达式,返回match对象 |
re.findall() | 搜索字符串,以列表类型返回全部能匹配的子串 |
re.split() | 将一个字符串按照正则表达式匹配结果进行分割,返回列表 |
re.finditer() | 搜索字符串,返回一个匹配结果的迭代类型,每一个迭代类型是match对象 |
re.sub() | 在一个字符串中替换所有匹配正则表达式的子串,返回替换后的字符串 |
re.compile(pattern[, flags])
compile 函数用于编译正则表达式,生成一个正则表达式( Pattern )对象,供 match() 和 search() 这两个函数使用。
re.search(pattern,string,flags=0)
在一个字符串中搜索匹配正则表达式的第一个位置,返回match对象。
- pattern:正则表达式的字符串或原生字符串表示
- string:待匹配字符串
- flags:正则表达式使用时的控制标记
修饰符 | 描述 |
---|---|
re.I | 使匹配对大小写不敏感 同re.IGNORECASE |
re.L | 做本地化识别(locale-aware)匹配 |
re.M | 多行匹配,影响 ^ 和 $ 同re.MULTILINE |
re.S | 使 . 匹配包括换行在内的所有字符 |
re.U | 根据Unicode字符集解析字符。这个标志影响 \w, \W, \b, \B. |
re.X | 该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解。 |
m = re.search('foo', 'seafood')
if m is not None:
print(m.group())
else:
print("no match")
output: foo
re.match(pattern, string, flags=0)
匹配成功re.match方法返回一个匹配的对象,否则返回None。
m = re.match('foo', 'seafood')
if m is not None:
print(m.groups())
else:
print("no match")
output: no match
使用group(num) 或 groups() 匹配对象函数来获取匹配表达式。
方法 | 描述 |
---|---|
group(num=0) | 匹配的整个表达式的字符串,group() 可以一次输入多个组号,在这种情况下它将返回一个包含那些组所对应值的元组。 |
groups() | 返回一个包含所有小组字符串的元组,从 1 到 所含的小组号。 |
m=re.match(r'(\d{3})\-(\d{3,8})$', '010-12345')
m.group() #output: '010-12345'
m.group(0) #output: '010-12345'
m.group(1) #output: '010'
m.group(2) #output: '12345'
m.groups() #output: ('010', '12345')
re.match只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None;而re.search匹配整个字符串,直到找到一个匹配。
match(str, pos, endpos)
从pos位置开始匹配,结束位置为endpos。位置信息默认为0和len(str)。
pattern = re.compile(r'dsa')
pattern.match('dsafww') #output: <_sre.SRE_Match object; span=(0, 3), match='dsa'>
pattern.match('dsdfdsafww',4) #output: <_sre.SRE_Match object; span=(4, 7), match='dsa'>
pattern.search('sadfadsaff') #output: <_sre.SRE_Match object; span=(5, 8), match='dsa'>
findall(str, pos, endpos)
返回所有匹配字串组成的list。
pattern = re.compile(r'\d+')
pattern.findall('abc2dfa3dsfasd5dfad') #output:['2', '3', '5']
finditer(str,pos,endpos)
找到所有匹配子串,返回由匹配结果(match object)组成的迭代器。
pattern = re.compile(r'\d+')
p = pattern.finditer('abc2fdas3klk9fds0dfdf')
print(p) #output:<callable_iterator object at 0x000002533754AE80>
for i in p:
print(i)
#output:<_sre.SRE_Match object; span=(3, 4), match='2'>
#output:<_sre.SRE_Match object; span=(8, 9), match='3'>
#output:<_sre.SRE_Match object; span=(12, 13), match='9'>
#output:<_sre.SRE_Match object; span=(16, 17), match='0'>
p = pattern.finditer('abc2fdas3klk9fds0dfdf')
for i in p:
print(i.group())
#output:2
#output:3
#output:9
#output:0
re.split(pattern,string,maxsplit=0,flags=0)
将一个字符串按照正则表达式匹配结果进行分割,返回列表类型。maxsplit:最大分隔数,剩余部分作为最后一个元素输出。
pattern = re.compile(r'[A-Z]+')
pattern.split("abcDefgHijkLmn") #output:['abc', 'efg', 'ijk', 'mn']
#Compare
'a b c'.split(' ') #output:['a', 'b', '', '', 'c']
re.split(r'[\s\,\;]+','a,;b, c') #output:['a', 'b', 'c']
sub(repl, string, count=0)
re.sub(pattern, repl, string, count=0, flags=0)
用repl替换string中每一个匹配的字串,返回替换后的字符串,若找不到匹配,则返回源字符串。
subn(),返回一个二元tuple(返回值,替换次数)。
pattern = re.compile(r'liKE', re.I)
pattern.sub(r'love', 'I like you, do u like me?') #output:'I love you, do u love me?'
pattern.subn(r'love', 'I like you, do u like me?') #output:('I love you, do u love me?', 2)
函数说明
match(), search(), findall(), finditer()这些既可以是pattern对象的函数,也可以模块直接调用,第一个参数为pattern。
match object函数
match.group()
返回match object中的字符串。
pattern = re.compile(r'(\w+) (\w+)')
m = pattern.match('kobe bryant, lakers')
print(m) #output:<_sre.SRE_Match object; span=(0, 11), match='kobe bryant'>
print(m.group()) #output:kobe bryant
print(m.group(1)) #output:kobe
print(m.group(2)) #output:bryant
print(m.group(1,2)) #output:('kobe', 'bryant')
print(m.groups()) #output:('kobe', 'bryant')
match.goups()
返回由所有分组匹配到的字符串组成的tuple。
match.start()
默认返回匹配字符串的起始位置,指定参数时,返回该分组匹配到的字符串的起始位置。
match.end()
返回结束位置。
match.span()
返回一个二元tuple表示匹配范围。
m = re.match(r'(\d+)\.(\d+)', '24.12321')
print(m.groups()) #output:('24', '12321')
print(m.start()) #output:0
print(m.start(1)) #output:0
print(m.start(2)) #output:3
print(m.end()) #output:8
print(m.end(1)) #output:2
print(m.span()) #output:(0, 8)
print(m.span(1)) #output:(0, 2)
print(m.span(2)) #output:(3, 8)
Reference:
Python 正则表达式-菜鸟教程http://www.runoob.com/python/python-reg-expressions.html
python | 史上最全的正则表达式https://blog.csdn.net/weixin_40907382/article/details/79654372
Python网络爬虫与信息提取(三)—— Re模块
https://www.cnblogs.com/yan-lei/p/7653362.html
廖雪峰老师的正则表达式https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/00143193331387014ccd1040c814dee8b2164bb4f064cff000
python官方文档re — Regular expression operations
https://docs.python.org/3/library/re.html