评论

收藏

[python] 最全的python re正则使用范例,有这一篇足够了

编程语言 编程语言 发布于:2021-06-26 10:11 | 阅读数:316 | 评论:0

一、什么是正则:

  1、正则表达式是一个特殊的字符序列,它能帮助你方便的检查一个字符串是否与某种模式匹配
  2、re 模块也提供了与这些方法功能完全一致的函数,这些函数使用一个模式字符串做为它们的第一个参数。
  总结一下,先整体了解re正则:

  • pattern = re.compile("\d") 将正则表达式编译成一个Pattern规则对象
  • pattern.match()  从开始位置开始往后查找,返回第一个符合规则的对象
  • pattern.search() 从任何位置开始往后查找,返回第一个符合规则的对象
  • pattern.findall()  所有的全部匹配,返回列表
  • pattern.finditer()  所有的全部匹配,返回的是一个迭代器
  • pattern.split()      分割字符串,返回列表
  • pattern.sub()      替换
二、re模块

2.1match方法
2.1.1语法:pattern.match(str, start, end)
  实例:
import re #导入re模块
<p>pattern = re.compile(r'\d+')  #此处加r表示不转义字符串</p>
<p>m = pattern.match('aaaa123bbb456')</p>
<p>m2 = pattern.match('aaaa123bbb456', 4,10)</p>
<p>print(m)   # None</p>
print(m2.group())  # 123
  match在没有匹配到数据的时候返回的是 None
  match匹配到数据后返回的是一个对象
2.1.2match分组匹配
import re
<p>pattern = re.compile(r'([a-z]+) ([a-z]+)', re.I)</p>
<p>m = pattern.match('hello world Hello Python')</p>
<p>print(m.group())  # hello world</p>
<p>print(m.group(0)) # hello world</p>
<p>print(m.group(1)) # hello</p>
print(m.group(2)) # world
三. re中的编译函数

3.1 compile方法
  那么如果一个正则表达式要重复使用几千次,出于效率的考虑,我们是不是应该先把这个正则先预编译好,接下来重复使用时就不再需要编译这个步骤了,直接匹配,提高我们的效率
import re
<p>re_telephone = re.compile(r'^(\d{3})-(\d{3,8})$')  # 编译</p>
<p>A = re_telephone.match('010-12345').groups()  # 使用</p>
<p>print(A)  # 结果 ('010', '12345')</p>
<p>B = re_telephone.match('010-8086').groups()  # 使用</p>
print(B)  # 结果 ('010', '8086')
  编译后生成Regular Expression对象,由于该对象自己包含了正则表达式,所以调用对应的方法时不用给出正则字符串。
3.2 search方法
  re.search()方法扫描整个字符串,并返回第一个成功的匹配。如果匹配失败,则返回None。
  与re.match()方法不同,re.match()方法要求必须从字符串的开头进行匹配,如果字符串的开头不匹配,整个匹配就失败了;
  re.search()并不要求必须从字符串的开头进行匹配,也就是说,正则表达式可以是字符串的一部分
  语法:re.search(pattern, string, flags=0)

  • pattern : 正则中的模式字符串。
  • string : 要被查找替换的原始字符串。
  • flags : 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。
例1:
import re
<p>content = 'Hello 123456789 Word_This is just a test 666 Test'</p>
<p>result = re.search('(\d+).<em>?(\d+).</em>', content)</p>
<p>print(result)</p>
<p>print(result.group())  # print(result.group(0)) 同样效果字符串</p>
<p>print(result.groups())</p>
print(result.group(1))
  运行结果:
&lt;_sre.SRE_Match object; span=(6, 49), match='123456789 Word_This is just a test 666 Test'&gt;
<p>123456789 Word_This is just a test 666 Test</p>
<p>('123456789', '666')</p>
<p>123456789</p>
<p>666</p>
Process finished with exit code 0
  例2:只匹配数字
import re
<p>content = 'Hello 123456789 Word_This is just a test 666 Test'</p>
<p>result = re.search('(\d+)', content)</p>
<p>print(result)</p>
<p>print(result.group())  # print(result.group(0)) 同样效果字符串</p>
<p>print(result.groups())</p>
  运行结果:
&lt;_sre.SRE_Match object; span=(6, 15), match='123456789'&gt;
<p>123456789</p>
<p>('123456789',)</p>
<p>123456789</p>
<p>Process finished with exit code 0</p>
3.3 finall方法
  返回一个包含所有匹配到的字符串的列表。

  •  pattern 匹配模式,由 re.compile 获得
  •  string 需要匹配的字符串
import re
<p>str = 'say hello world! hello python'</p>
<p>pattern = re.compile(r'(?P&lt;first&gt;h\w)(?P&lt;symbol&gt;l+)(?P&lt;last&gt;o\s)') # 分组,0 组是整个 world!, 1组 or,2组 ld!</p>
<p>match = re.findall(pattern, str)</p>
print(match)
  运行结果:
[('he', 'll', 'o '), ('he', 'll', 'o ')]
  另外,多讲两个名字类似的:
  re.finditer :re.finditer(pattern, string[, flags=0])
  re.findall:re.findall(pattern, string[, flags=0])

  • pattern compile 生成的正则表达式对象,或者自定义也可
  •  string 要匹配的字符串
findall 返回一个包含所有匹配到的字符的列表,列表类以元组的形式存在。  finditer 返回一个可迭代对象。
  例1:
pattern = re.compile(r'\d+@\w+.com') #通过 re.compile 获得一个正则表达式对象
<p>result_finditer = re.finditer(pattern, content)</p>
<p>print(type(result_finditer))</p>
<p>print(result_finditer) # finditer 得到的结果是个可迭代对象</p>
<p>for i in result_finditer: # i 本身也是可迭代对象,所以下面要使用 i.group()</p>
<p>print(i.group())</p>
<p>result_findall = re.findall(pattern, content)</p>
<p>print(type(result_findall)) # findall 得到的是一个列表</p>
<p>print(result_findall)</p>
<p>for p in result_finditer:</p>
 print(p)
  运行结果:
&lt;class 'callable_iterator'&gt;
<p>&lt;callable_iterator object at 0x10545ec88&gt;</p>
<p>123456@163.com</p>
<p>234567@163.com</p>
<p>345678@163.com</p>
<p>&lt;class 'list'&gt;</p>
['123456@163.com', '234567@163.com', '345678@163.com']
由结果可知:finditer 得到的是可迭代对象,finfdall 得到的是一个列表例2:
import re
<p>content = '''email:123456@163.com</p>
<p>email:234567@163.com</p>
<p>email:345678@163.com</p>
<p>'''</p>
<p>pattern = re.compile(r'(?P&lt;number&gt;\d+)@(?P&lt;mail_type&gt;\w+).com')</p>
<p>result_finditer = re.finditer(pattern, content)</p>
<p>print(type(result_finditer))</p>
<p>print(result_finditer)</p>
<p>iter_dict = {} # 把最后得到的结果</p>
<p>for i in result_finditer:</p>
<p>print('邮箱号码是:', i.group(1),'邮箱类型是:',i.group(2))</p>
<p>number = i.group(1)</p>
<p>mail_type = i.group(2)</p>
<p>iter_dict.setdefault(number, mail_type) # 使用 dict.setdefault 创建了一个字典</p>
<p>print(iter_dict)</p>
<p>print('+++++++++++++++++++++++++++++++')</p>
<p>result_findall = re.findall(pattern, content)</p>
<p>print(result_findall)</p>
print(type(result_findall))
  运行结果:
&lt;class 'callable_iterator'&gt;
<p>&lt;callable_iterator object at 0x104c5cbe0&gt;</p>
<p>邮箱号码是: 123456 邮箱类型是: 163</p>
<p>邮箱号码是: 234567 邮箱类型是: 163</p>
<p>邮箱号码是: 345678 邮箱类型是: 163</p>
<p>{'123456': '163', '234567': '163', '345678': '163'}</p>
<p>+++++++++++++++++++++++++++++++</p>
<p>[('123456', '163'), ('234567', '163'), ('345678', '163')]</p>
&lt;class 'list'&gt;
  finditer 得到的可迭代对象 i,也可以使用 lastindex,lastgroup 方法。
  print('lastgroup 最后一个被捕获的分组的名字',i.lastgroup)
  findall 当正则没有分组,返回就是正则匹配。
e.findall(r"\d+@\w+.com", content)
['2345678@163.com', '2345678@163.com', '345678@163.com']
  有一个分组返回的是分组的匹配
re.findall(r"(\d+)@\w+.com", content)
['2345678', '2345678', '345678']
  多个分组时,将结果作为 元组,一并存入到 列表中。
re.findall(r"(\d+)@(\w+).com", content)
[('2345678', '163'), ('2345678', '163'), ('345678', '163')]
  小结:search找到就返回,finall全部找到才返回
3.5 split方法
  split能够按照所能匹配的字串将字符串进行切分,返回切分后的字符串列表
  语法:re.split(pattern, string[, maxsplit=0, flags=0])
  pattern:匹配的字符串
  string:需要切分的字符串
  maxsplit:分隔次数,默认为0(即不限次数)
  flags:标志位,用于控制正则表达式的匹配方式,比如:是否区分大小写
import re
<p>line = 'aaa bbb ccc;ddd   eee,fff'</p>
<p>print(line)</p>
'aaa bbb ccc;ddd   eee,fff'
  单字符切割
re.split(r';',line)
<p>结果:</p>
['aaa bbb ccc', 'ddd\teee,fff']
  两个字符以上切割需要放在 [ ] 中
re.split(r'[;,]',line)
<p>结果:</p>
['aaa bbb ccc', 'ddd\teee', 'fff']
  所有空白字符切割
re.split(r'([;])',line)
<p>结果:</p>
['aaa bbb ccc', ';', 'ddd\teee,fff']
  不想保留分隔符,以(?:...)的形式指定
re.split(r'(?:[;])',line)
<p>结果:</p>
['aaa bbb ccc', 'ddd\teee,fff']
四. 贪婪模式与非贪婪模式

  正则表达式通常用于在文本中查找匹配的字符串。
  Python里数量词默认是贪婪的(在少数语言里也可能是默认非贪婪),总是尝试匹配尽可能多的字符;
  非贪婪则相反,总是尝试匹配尽可能少的字符。在"*","?","+","{m,n}"后面加上?,使贪婪变成非贪婪
  总结一下:

  • 贪婪:在满足条件情况下尽可能匹配到数据
  • 非贪婪:满足条件就可以,在"<em>","?","+","{m,n}"后面加上?,就能将贪婪变成非贪婪.
import re
<br><h1>贪婪匹配</h1><br>
<p>greedy_pattern = re.compile(r'ab.</em>c')</p>
<p>greedy_match = greedy_pattern.match('abcaxc')</p>
<p>print("贪婪匹配结果:" + greedy_match.group())</p>
<br><h1>非贪婪匹配</h1><br>
<p>not_greedy_pattern = re.compile(r'ab.*?c')</p>
<p>not_greedy_match = not_greedy_pattern.match('abcaxc')</p>
print("非贪婪匹配结果:" + not_greedy_match.group())
  输出:
贪婪匹配结果:abcaxc
非贪婪匹配结果:abc
关注下面的标签,发现更多相似文章