Loading

re模块

在Python中需要通过正则表达式对字符串进⾏匹配的时候,可以使⽤⼀个python自带的模块,名字为re。

引子

有如下数据,如果想找到所有电话,如下代码可以实现

1     张三    15234558644
2     王二    13546125484
3     王五    12454554687
with open("新建 文本文档.txt", "r", encoding="utf-8") as f:
    for line in f:
        a, b, c = line.split()
        if c.startswith("1"):
            print(c)

想要更简便实现查找,此时就要用到re模块

import re

with open("新建 文本文档.txt", "r", encoding="utf-8") as f:
    phone_list = re.findall("[0-9]{11}", f.read())  
    print(phone_list)  # ['15234558644', '13546125484', '12454554687']

re的匹配语法

image

re匹配规则

image

示例

import re

# 匹配包含
res = re.search(".", "text")  # <re.Match object; span=(0, 1), match='t'>
print(res.group())  # t

# 分组匹配
res = re.search("(abc){2}a(123|45)", "abcabca456c")  # <re.Match object; span=(0, 9), match='abcabca45'>
print(res.group())  # abcabca45

# 匹配不到时返回None,此时不能.group()
res = re.search("(abc){3}a(123|45)", "abcabca456c")  # None
print(res)  # None

案例-身份证匹配

对于18位身份证

  • 前六位数字表示地址码.例如,110101 代表北京市东城区。
  • 第七位至十四位数字表示出生日期码
  • 第十五位至十七位数字表示顺序码,它表示在同一地址码所标识的区域范围内,对同年、同月、同日出生的人编定的顺序号,顺序码的奇数分配给男性,偶数分配给女性。
  • 第十八位数字是校验码,它是根据前面十七位数字码,按照 ISO 7064:1983.MOD 11-2 校验码计算出来的检验码。校验码的计算方法较为复杂,主要是为了验证身份证号码的合法性和准确性。
import re

my_id = "411282200412121122"

# 1.返回身份证号前10位
res = re.search("([0-9]{3})([0-9]{3})([0-9]{4})", my_id)
print(res.group())  # 4112822004

# 2.以元组方式返回
print(res.groups())  # ('411', '282', '2004')

# 3.以字典方式返回
res2 = re.search("(?P<province>[0-9]{3})(?P<city>[0-9]{3})(?P<year>[0-9]{4})", my_id)
print(res2.groupdict())  # {'province': '411', 'city': '282', 'year': '2004'}

# res2也可用1,2方式返回
print(res2.group())  # 4112822004
print(res.groups())  # ('411', '282', '2004')

示例2

import re

# \d匹配一个数字
print(re.search("\d", "12345").group())  # 1

# re.split()分隔
print(re.split("\d", "zhang2yi3zhuo"))  # ['zhang', 'yi', 'zhuo']
print(re.split("\w", "zhang2yi3zhuo"))  # ['', '', '', '', '', '', '', '', '', '', '', '', '', '']

# re.sub()替换
# 将"abc替换为"ABC",最多替换2次
print(re.sub("abc", "ABC", "abc123", count=2))  # ABC123
print(re.sub("abc", "ABC", "abcabcabc123", count=2))  # ABCABCabc123

# re.fullmatch()全部匹配(精确匹配)
# 需要全部一样才匹配成功
print(re.fullmatch("zhangyizhuo", "zhangyizhuo123"))  # None
print(re.fullmatch("zhangyizhuo123", "zhangyizhuo123"))  # <re.Match object; span=(0, 14), match='zhangyizhuo123'>
print(re.fullmatch("zhangyizhuo123", "zhangyizhuo123").group())  # zhangyizhuo123

# re.match()从头开始匹配
print(re.match("abc", "123abc"))  # None
print(re.match("abc", "abc123"))  # <re.Match object; span=(0, 3), match='abc'>
print(re.match("abc", "abc123").group())  # abc

re.compile & re.match

re.compile可以给正则表达式设置匹配模式,赋值给变量以便后续使用

import re

# re.compile()可以将定义好的匹配模式赋给一个变量
pattern = re.compile("\d{3}")

# 之后可以调用此匹配模式
print(re.match(pattern, "123abc456"))  # <re.Match object; span=(0, 3), match='123'>
print(re.match(pattern, "123abc456").group())  # 123

Flags标志符

flags作为re.search(),re.match()等方法的第三个参数,可以扩展正则表达式的使用

image

import re

# re.I忽略大小写
print(re.search("abc", "Abc123"))  # None
print(re.search("abc", "Abc123", re.I))  # <re.Match object; span=(0, 3), match='Abc'>

# re.M多行模式,改变'^'或'$'行为
print(re.search("^abc", "abc123"))  # <re.Match object; span=(0, 3), match='abc'>
print(re.search("^abc", "aabc123"))  # None
print(re.search("^abc", "a\nabc123"))  # None
print(re.search("^abc", "a\nabc123", re.M))  # <re.Match object; span=(2, 5), match='abc'>

# re.S改变'.'的行为,使'.'也可以匹配\n
print(re.search(".{3}", "bc\n"))  # None
print(re.search(".{3}", "bc\n", re.S))  # <re.Match object; span=(0, 3), match='bc\n'>

# re.X使得可以给表达式写注释,多用于复杂正则表达式中
# r""表示原始字符串(raw string):会让\变为普通字符,使其失去转义能力
pattern = re.compile(r"""
(\d{3}) # 匹配省份
(\d{3}) # 匹配市区
(\d{4}) # 匹配出生年
""", re.X)

print(re.match(pattern, "411282200412121122"))  # <re.Match object; span=(0, 10), match='4112822004'>
print(re.match(pattern, "411282200412121122").group())  # 4112822004
posted @ 2024-11-23 10:59  一只大学生  阅读(4)  评论(0编辑  收藏  举报