1、正则表达式概述
正则表达式(英语:Regular Expression,在代码中常简写为regex、regexp或RE),是计算机科学的一个概念。
正则表达式使用单个字符串来描述、匹配一系列匹配某个句法规则的字符串。
在很多文本编辑器里,正则表达式通常被用来检索、替换那些匹配某个模式的文本。
2、re模块
2.1re 模块
使 Python语言拥有全部的正则表达式功能。
re 模块提供了一些函数,这些函数使用一个模式字符串做为它们的第一个参数,用于正则表达式匹配和替换。
2.2re模块的使用
- re.match 函数
re.match 尝试从字符串的起始位置匹配一个模式,若字符串起始位置匹配正则表达式,则match方法返回匹配对象(Match Object),如果不是起始位置匹配成功的话,match()就返回none(注意不是“空字符串”)。
- 语法:
re.match(pattern,string,flags=0)
- 参数:
pattern – 匹配的正则表达式 string – 要匹配的字符串。 flags – 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。 匹配对象Macth Object具有group方法,我们可以使用group(num) 或 groups() 匹配对象函数来获取匹配表达式。 group(num=0) 匹配的整个表达式的字符串,group() 可以一次输入多个组号,在这种情况下它将返回一个包含那些组所对应值的元组。 groups() 返回一个包含所有小组字符串的元组,从 1 到 所含的小组号。
示例1: # 导入re模块 import re # 使用match方法进行匹配操作 result = re.match(正则表达式,要匹配的字符串) # 如果上一步匹配到数据的话,可以使用group方法来提取数据 result.group()
示例2: import re ret = re.match("taobao","taobao.com") print(ret) print(ret.group()) 运行结果: <_sre.SRE_Match object; span=(0,6),match=‘taobao‘> taobao
3、表示字符
正则表达式的单字符匹配:
字体 | 功能 |
---|---|
. | 匹配任意一个字符(除了\n) |
[] | 匹配[]中列举的字符 |
\d | 匹配数字,即0-9 |
\D | 匹配非数字,即不是数字 |
\s | 匹配空白,即 空格,tab键 |
\S | 匹配非空白 |
\w | ==匹配包括下划线的任何单词字符。类似但不等价于“[A-Za-z0-9_]”,这里的"单词"字符使用Unicode字符集。== |
\W | 匹配非单词字符 |
匹配中文字符的正则表达式: [\u4e00-\u9fa5]
- 示例1:‘.’
匹配任意字符,除了换行符,当re.DOTALL标记被指定时,则可以匹配包括换行符的任意字符。
ret = re.match(‘.‘,‘a‘) print(ret.group()) ret = re.match(‘.‘,‘A‘) print(ret.group()) ret = re.match(‘.‘,‘ ‘) print(ret.group()) ret = re.match(‘.‘,‘\nab‘) print(ret.group()) 错误 ret = re.match(‘..‘,‘\rab‘) print(ret.group()) ret = re.match(‘..‘,‘\tab‘) print(ret.group()) ret = re.match(‘.‘,‘好好学习‘) print(ret.group()) ret = re.match(‘....‘,‘好好学习‘) print(ret.group())
- 示例2:’[ ]‘
用来表示一组字符,单独列出:[amk] 匹配 ‘a’,’m’或’k’
ret = re.match(‘[Hh]‘,‘hello‘) print(ret.group()) ret = re.match(‘[Hh]‘,‘Hello‘) print(ret.group()) ret = re.match(‘[A-Z]‘,‘Hello‘) print(ret.group()) ret = re.match(‘[0-9a-z]‘,‘00‘) print(ret.group()) ret = re.match(‘[0-9a-z]‘,‘aa‘) print(ret.group()) ret = re.match(‘[\u4e00-\u9fa5]*‘,‘陈佳睿‘) print(ret) print(ret.group())
- 示例3:’\d,\D,\s,\S‘
\d – 匹配一个数字字符。等价于 [0-9]。
\D –匹配一个非数字字符。等价于 [^0-9]。
\s –匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。
\S –匹配任何非空白字符。等价于 [^ \f\n\r\t\v]。
ret = re.match(‘小米\d‘,‘小米6‘) print(ret.group()) ret = re.match(‘小\D\d‘,‘小米6‘) print(ret.group()) ret = re.match(‘\s‘,‘ 小米‘) print(ret) ret = re.match(‘\s‘,‘\nab‘) print(ret) ret = re.match(‘\S‘,‘小米‘) print(ret) ret = re.match(‘\S‘,‘0123‘) print(ret) ret = re.match(‘\S\S\S‘,‘x米6‘) print(ret) 运行结果: 小米6 小米6 <_sre.SRE_Match object; span=(0,1),match=‘ ‘> <_sre.SRE_Match object; span=(0,match=‘\n‘> <_sre.SRE_Match object; span=(0,match=‘小‘> <_sre.SRE_Match object; span=(0,match=‘0‘> <_sre.SRE_Match object; span=(0,3),match=‘x米6‘>
- 示例4:’\w,\W‘
\w ==匹配包括下划线的任何单词字符。类似但不等价于“[A-Za-z0-9_]”,这里的"单词"字符使用Unicode字符集。==。
\W 匹配任何非单词字符。等价于 ‘[^A-Za-z0-9_]’。
ret = re.match(‘\w‘,‘hello‘) print(ret) ret = re.match(‘\w\w‘,‘_hello‘) print(ret) ret = re.match(‘\w‘,‘陈‘) print(ret) ret = re.match(‘\W\W\w‘,‘。.Hello‘) print(ret) ret = re.match(‘\W‘,‘陈hello‘) print(ret) #None ret = re.match(‘\W‘,‘陈hello‘,re.ASCII) #匹配各个国家文字 print(ret) #<_sre.SRE_Match object; span=(0,match=‘陈‘> ret = re.match(‘[\u4e00-\u9fa5]‘,‘哈hello‘) print(ret) 运行结果: <_sre.SRE_Match object; span=(0,match=‘h‘> <_sre.SRE_Match object; span=(0,2),match=‘_h‘> <_sre.SRE_Match object; span=(0,match=‘陈‘> <_sre.SRE_Match object; span=(0,match=‘。.H‘> None <_sre.SRE_Match object; span=(0,match=‘哈‘>
4、原始字符串
>>> mm = "c:\\a\\b\\c" >>> mm ‘c:\\a\\b\\c‘ >>> print(mm) c:\a\b\c >>> print(mm) c:\a\b\c >>> re.match("c:\\\\",mm).group() ‘c:\\‘ >>> ret = re.match("c:\\\\",mm).group() >>> print(ret) c:>>> ret = re.match("c:\\\\a",mm).group() >>> print(ret) c:\a >>> ret = re.match(r"c:\\a",mm).group() >>> print(ret) c:\a >>> ret = re.match(r"c:\a",mm).group() Traceback (most recent call last): File "<stdin>",line 1,in <module> AttributeError: ‘nonetype‘ object has no attribute ‘group‘
python中字符串前面加上 r 表示原生字符串
与大多数编程语言相同,正则表达式里使用””作为转义字符,这就可能造成反斜杠困扰。假如你需要匹配文本中的字符””,那么使用编程语言表示的正则表达式里将需要4个反斜杠””:前两个和后两个分别用于在编程语言里转义成反斜杠,转换成两个反斜杠后再在正则表达式里转义成一个反斜杠。
Python里的原生字符串很好地解决了这个问题,有了原始字符串,你再也不用担心是不是漏写了反斜杠,写出来的表达式也更直观。
>>> ret = re.match(r"c:\\a",mm).group() >>> print(ret) c:\a
5、表示数量
匹配多个字符的相关格式
字符 | 功能 |
---|---|
* | 匹配前一个字符出现0次或者无限次,即可有可无 |
+ | 匹配前一个字符出现1次或者无限次,即至少有1次 |
? | 匹配前一个字符出现1次或者0次,即要么有1次,要么没有 |
{m} | 匹配前一个字符出现m次 |
{m,} | 匹配前一个字符至少出现m次 |
{m,n} | 匹配前一个字符出现从m到n次 |
6、表示边界
字符 | 功能 |
---|---|
^ | 匹配字符串开头 |
$ | 匹配字符串结尾 |
\b | 匹配一个单词的边界 |
\B | 匹配非单词边界 |
- 示例1:$
需求:匹配163.com的邮箱地址
import re # 正确的地址 ret = re.match("[\w]{4,20}@163\.com","@L_404_0@") ret.group() # 不正确的地址 ret = re.match("[\w]{4,"[email protected]") ret.group() # 通过$来确定末尾 ret = re.match("[\w]{4,20}@163\.com$","[email protected]") ret.group()
- 示例2: \b
>>> re.match(r".*\bver\b","ho ver abc").group() ‘ho ver‘ >>> re.match(r".*\bver\b","ho verabc").group() Traceback (most recent call last): File "<stdin>",in <module> AttributeError: ‘nonetype‘ object has no attribute ‘group‘ >>> re.match(r".*\bver\b","hover abc").group() Traceback (most recent call last): File "<stdin>",in <module> AttributeError: ‘nonetype‘ object has no attribute ‘group‘
- 示例3:\B
>>> re.match(r".*\Bver\B","hoverabc").group() ‘hover‘ >>> re.match(r".*\Bver\B",in <module> AttributeError: ‘nonetype‘ object has no attribute ‘group‘ >>> re.match(r".*\Bver\B","ho ver abc").group() Traceback (most recent call last): File "<stdin>",in <module> AttributeError: ‘nonetype‘ object has no attribute ‘group‘
7、匹配分组
字符 | 功能 |
---|---|
| | 匹配左右任意一个表达式 |
(ab) | 将括号中字符作为一个分组 |
\num | 引用分组num匹配到的字符串 |
(?P | 分别起组名 |
(?P=name) | 引用别名为name分组匹配到字符串 |
- 示例1:|
需求:匹配出0-100之间的数字
import re ret = re.match("[1-9]?\d","8") print(ret) ret = re.match("[1-9]?\d","78") print(ret) # 不能正常匹配到的情况 ret = re.match("[1-9]?\d","08") print(ret) # 修正之后的 ret = re.match("[1-9]?\d$","8") print(ret) # 添加| ret = re.match("[1-9]?\d$|100","8") print(ret) ret = re.match("[1-9]?\d$|100","78") print(ret) ret = re.match("[1-9]?\d$|100","100") print(ret) 运行结果: <_sre.SRE_Match object; span=(0,match=‘8‘> <_sre.SRE_Match object; span=(0,match=‘78‘> <_sre.SRE_Match object; span=(0,match=‘100‘>
- 示例2:( )
import re ret = re.match("\w{4,"[email protected]") ret.group() ret = re.match("\w{4,20}@(163|126|qq)\.com","[email protected]") ret.group() ret = re.match("\w{4,"[email protected]") ret.group() ret = re.match("\w{4,"[email protected]") ret.group()
>>> ret = re.match("([^-]*)-(\d+)","010-12345678") >>> ret.group() ‘010-12345678‘ >>> ret.group(1) ‘010‘ >>> ret.group(2) ‘12345678‘
- 示例3:
需求:匹配出hh
import re # 能够完成对正确的字符串的匹配 ret = re.match("<[a-zA-Z]*>\w*</[a-zA-Z]*>","<html>hh</html>") ret.group() # 如果遇到非正常的html格式字符串,匹配出错 ret = re.match("<[a-zA-Z]*>\w*</[a-zA-Z]*>","<html>hh</htmlbalabala>") ret.group() # 正确的理解思路:如果在第一对<>中是什么,按理说在后面的那对<>中就应该是什么 # 通过引用分组中匹配到的数据即可,但是要注意是元字符串,即类似 r""这种格式 ret = re.match(r"<([a-zA-Z]*)>\w*</\1>","<html>hh</html>") ret.group() # 因为2对<>中的数据不一致,所以没有匹配出来 ret = re.match(r"<([a-zA-Z]*)>\w*</\1>","<html>hh</htmlbalabala>") ret.group()
- 示例4:\number
需求:匹配出
www.taobao.com
import re ret = re.match(r"<(\w*)><(\w*)>.*</\2></\1>","<html><h1>www.taobao.com</h1></html>") ret.group() ret = re.match(r"<(\w*)><(\w*)>.*</\2></\1>","<html><h1>www.taobao.com</h2></html>") ret.group()
- 示例5:(?P
需求:匹配出
www.taobao.com
import re ret = re.match(r"<(?P<name1>\w*)><(?P<name2>\w*)>.*</(?P=name2)></(?P=name1)>","<html><h1>www.taobao.com</h1></html>") ret.group() ret = re.match(r"<(?P<name1>\w*)><(?P<name2>\w*)>.*</(?P=name2)></(?P=name1)>","<html><h1>www.taobao.com</h2></html>") ret.group()
(?P
8、re模块的高级用法
8.1search
需求:匹配出文章阅读的次数 import re ret = re.search(r"\d+","阅读次数为 9999") print(ret.group()) 9999
8.2findall
需求:统计出python、c、c++相应文章阅读的次数 import re ret = re.findall(r"\d+","python = 9999,c = 7890,c++ = 12345") print(ret) [‘9999‘,‘7890‘,‘12345‘]
8.3sub 将匹配到的数据进行替换
需求:将匹配到的阅读次数加1 方法1: import re ret = re.sub(r"\d+",‘998‘,"python = 997") print(ret) python = 998 方法2: import re def add(temp): strNum = temp.group() num = int(strNum) + 1 return str(num) ret = re.sub(r"\d+",add,"python = 997 java=100") print(ret) ret = re.sub(r"\d+","python = 99") print(ret) python = 998 java=101 python = 100
从下面的字符串中取出文本 <div> <p>岗位职责:</p> <p>完成推荐算法、数据统计、接口、后台等服务器端相关工作</p> <p><br></p> <p>必备要求:</p> re.sub(r‘</?\w*>|\n|\s‘,‘‘,s)
8.4split
- 根据匹配进行切割字符串,并返回一个列表
需求:切割字符串“info:xiaoZhang 33 shandong” import re ret = re.split(r‘:| ‘,‘info:xiaoZhang 33 shandong‘) print(ret) [‘info‘,‘xiaoZhang‘,‘33‘,‘shandong‘]
9、贪婪和非贪婪
Python里数量词默认是贪婪的(在少数语言里也可能是默认非贪婪),总是尝试匹配尽可能多的字符;
非贪婪则相反,总是尝试匹配尽可能少的字符。
在"*","?","+","{m,n}"后面加上?,使贪婪变成非贪婪。
s="This is a number 234-235-22-423" ret = re.match(".+(\d+-\d+-\d+-\d+)",s) print(ret.group()) This is a number 234-235-22-423 ret = re.match(".+?(\d+-\d+-\d+-\d+?)",s) print(ret.group()) This is a number 234-235-22-4
正则表达式模式中使用到通配字,那它在从左到右的顺序求值时,会尽量“抓取”满足匹配最长字符串,在我们上面的例子里面,“.+”会从字符串的启始处抓取满足模式的最长字符,其中包括我们想得到的第一个整型字段的中的大部分,“\d+”只需一位字符就可以匹配,所以它匹配了数字“4”,而“.+”则匹配了从字符串起始到这个第一位数字4之前的所有字符。 解决方式:非贪婪操作符“?”,这个操作符可以用在"*","?"的后面,要求正则匹配的越少越好。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。