语法
常用匹配规则
通过py中的re模块来学习并使用正式表达式
import re
匹配字符
| 符号 | 说明 |
|---|---|
| . | 匹配任意一个字符,除了换行符\n |
| [abc] | 匹配abc中的任意一个字符 |
| \d | 匹配一个数字,即0-9 |
| \D | 匹配非数字,即不是数字 |
| \s | 匹配空白,即空格,tab键 |
| \S | 匹配非空白,除空格,tab键之类的 |
| \w | 匹配单词字符,即a-z、A-Z、_(字母数字下划线) |
| \W | 匹配非单词字符 |
匹配字符数量
| 符号 | 说明 |
|---|---|
| * | 匹配前一个字符出现0次或无限次,即可有可无 |
| + | 出现1次或者无限次,即至少有1次 |
| \? | 出现1次或者0次,即要么1次,要么没有 |
| {m} | 出现m次 |
| {m,} | 至少出现m次 |
| {n,m} | 出现从n到m次 |
分组匹配
| 符号 | 说明 |
|---|---|
| | | 匹配左右任意一个表达式 |
| (ab) | 讲括号中字符作为一个分组 |
| \num | 引用分组num匹配到的字符串 |
| (?P) | 分组起别名 |
| (?P=name) | 引用别名为name分组匹配到的字符串 |
re库
re.complie
re.compile()是用来优化正则的,它将正则表达式转化为对象。re.search(pattern, string)的调用方式就转换为 pattern.search(string)的调用方式,多次调用一个正则表达式就重复利用这个正则对象,可以实现更有效率的匹配
语法格式
re.compile(pattern, flags=0)
- pttern 匹配模式。即要表达的正则表达式
从compile()函数的定义中,可以看出返回的是一个匹配对象,它单独使用就没有任何意义,需要和findall(), search(), match()搭配使用。
实践操作
常规的re.findall的写法是这样写的,但是我们可以结合compile()函数来使用
import reobj=re.findall(r'1\d{10}','我的手机号码是:152352100000')print(obj)
输出的结果为:[‘15235210000’]
与compile()函数结合:
import repatter=re.compile(r'1\d{10}')obj=patter.findall('我的手机号码是:1523521000077')print(obj)
re.findall
在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果有多个匹配模式,则返回元组列表,如果没有找到匹配的,则返回空列表
语法格式
re.findall(pattern, string, flags=0)或pattern.findall(string[, pos[, endpos]])
- pattern 匹配模式。
- string 待匹配的字符串。
- pos 可选参数,指定字符串的起始位置,默认为 0。
- endpos 可选参数,指定字符串的结束位置,默认为字符串的长度。
实践操作
输出结果为:[‘10086’, ‘10011’]import re #导入re模块lst=re.findall(r'\d+','我的电话是:10086,她的电话是:10011')#检索字符串中所有的数字print(lst)
输出结果为:[‘2345’, ‘09098’]import relst1=re.findall(r'\d+','ysegsde2345dgtesget09098')print(lst1)
re.finditer
语法格式
和 findall 类似,在字符串中找到正则表达式所匹配的所有子串,并把它们作为一个迭代器返回。
re.finditer(pattern, string, flags=0)
- pattern 匹配模式。
-
实践操作
import reitem=re.finditer(r'\d+','我的电话是:10086,她的电话是:10011')for i in item:print(i.group()) #要通过group来取数据
re.sub
语法格式
re.sub(pattern, repl, string, count=0, flags=0)
pattern : 正则中的模式字符串。
- repl : 替换的字符串,也可为一个函数。
- string : 要被查找替换的原始字符串。
- count : 模式匹配后替换的最大次数,默认 0 表示替换所有的匹配。
flags : 编译时用的匹配模式,数字形式。
1).re.I(re.IGNORECASE): 忽略大小写2).re.M(MULTILINE): 多行模式,改变'^'和'$'的行为3).re.S(DOTALL): 点任意匹配模式,改变'.'的行为4).re.L(LOCALE): 使预定字符类 \w \W \b \B \s \S 取决于当前区域设定5).re.U(UNICODE): 使预定字符类 \w \W \b \B \s \S \d \D 取决于unicode定义的字符属性6).re.X(VERBOSE): 详细模式。这个模式下正则表达式可以是多行,忽略空白字符,并可以加入注释
实践操作
#re.sub 实现目标的搜索和查找 2021-12-13data='Pyhton是很受欢迎的编程语言'res=re.sub(r'[a-zA-Z]+','C#',data) #字符集的范围+号代表字符模式出现1次以上print(res)
输出结果为:C#是很受欢迎的编程语言
# 将里面的分数都替换成100分msg='语文=99,数学=78,英语=90'm=re.sub(r'\d+','100',msg)print(m)
输出结果为:语文=100,数学=100,英语=100
import redata='save your time'res=re.sub('s','S',data) #讲小s替换成大写的Sprint(res)
re.macth
尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none
匹配成功re.match方法返回一个匹配的对象,否则返回None。可以使用group(num) 或 groups() 匹配对象函数来获取匹配表达式语法格式
re.match(pattern, string, flags=0)
pattern 匹配模式。
- string 待匹配的字符串。
实践操作
在起始位置匹配
输出结果为:import res=re.match(r'\d+','12353442wwww上的人人dddd234g') #从头开始,是否符合是数字要求,如果是,返回数字,如果不是,返回noneprint(s)
如果要正常的输出,加上一个.group()<_sre.SRE_Match object; span=(0, 8), match='12353442'> #表示有匹配对象
输出结果为:12353442import res=re.match(r'\d+','12353442wwww上的人人dddd234g') #从头开始,是否符合是数字要求,如果是,返回数字,如果不是,返回noneprint(s.group())
在起始位置不匹配
import res=re.match(r'\d+','wwww上的人人dddd234g') #从头开始,是否符合是数字要求,如果是,返回数字,如果不是,返回noneprint(s)
re.search
扫描整个字符串并返回第一个成功的匹配。从任何一个地方开始匹配,只匹配一次。
注意:是一次匹配,如果后面还有匹配的也不会查找了。使用group()来获取数据
语法格式
re.search(pattern, string, flags=0)
- pattern 匹配模式。
- string 待匹配的字符串。
实践操作
输出结果为:import rer=re.search('abc','helabcloabc')print(r)
如果要正常的输出,加上一个.group()<_sre.SRE_Match object; span=(3, 6), match='abc'> #表示有匹配对象
输出结果为:abcimport rer=re.search('abc','helabcloabc')print(r.group())
输出结果为:10086#2022-01-21 search,找到一个结果就返回,返回的结果是match对象,拿到数据需要.group()import reitem=re.search(r'\d+','我的电话是:10086,她的电话是:10011')print(item.group())
Match对象有几个常用的方法:group(): 用于获得一个或多个分组匹配的字符串,当要获得整个匹配的子串时,可直接使用 group() 或 group(0)span(): 返回匹配字符串的起始位置start():用于获取分组匹配的子串在整个字符串中的起始位置(子串第一个字符的索引),参数默认值为 0;end():用于获取分组匹配的子串在整个字符串中的结束位置(子串最后一个字符的索引+1),参数默认值为 0
import rer=re.search('abc','helabcloabc')if r:print(r.group())print(r.span())print(r.start())print(r.end())
输出结果为:
import rematch=re.search(r'([a-z]+) ([a-z]+)','hello Kitty hellobaby hello world')# 注意此时是区分大小写的if match:print(match.group(0))print(match.group(1))#获取第一个分组的字符串print(match.group(2))#获取第二个分组的字符串print(match.groups())
输出结果为:
上面的正则表达式表示两组有多个a-z之间的任意字符组成的多个字符串,并且两组之间是有空格的。其中match.groups()表示的意思是(m.group(1), m.group(2), …)search只要找到符合要求的字符串则不会继续查找,但是事实上后面仍然符合正则的仍然是存在的。比如:hello world
要想所有的都获取到,考虑使用findall()
