Python 正则表达式

        正则表达式(Regular Expression,常简写为 regex 或 regexp)是一种用于匹配、查找、替换文本中特定模式的强大工具,在很多编程语言中都有相应的实现,Python 也不例外,通过内置的 re 模块来支持正则表达式的使用。以下是关于正则表达式的详细介绍:

1. 基本概念

        正则表达式由普通字符(例如字母、数字、标点等)和特殊字符(具有特定匹配含义的字符)组成,通过特定的语法规则构建出用于描述文本模式的表达式,进而可以对目标文本进行相关操作。

        例如,正则表达式 abc 就是简单地匹配文本中连续出现的 abc 这三个字符;而像 \d 这样的特殊字符组合则代表匹配任意一个数字(0 - 9)。

2. 常用特殊字符及语法

字符类

  • \d:匹配任意一个数字,等同于 [0-9],例如正则表达式 \d{3} 可以匹配连续出现的三个数字,像 123567 等都能被匹配到。
  • \D:与 \d 相反,匹配任意一个非数字字符,例如正则表达式 \D+ 可以匹配连续出现的多个非数字字符,像 abc!@# 等符合要求的内容都会被匹配。
  • \w:匹配包括下划线在内的任何字母数字字符,等同于 [a-zA-Z0-9_],比如 \w{5} 能匹配由字母数字或下划线组成的长度为 5 的字符串,像 abcdea1b2c 等都满足。
  • \W:与 \w 相反,匹配任何非字母数字下划线的字符,例如 \W* 可以匹配连续出现的任意非字母数字下划线字符序列,像 !@#&*() 等都可被匹配。
  • [ ]:自定义字符类,用来指定要匹配的一组字符范围,例如 [abc] 表示匹配 ab 或者 c 这三个字符中的任意一个;而 [a-z] 则表示匹配所有小写字母。
量词
  • *:匹配前面的元素零次或多次,例如正则表达式 a* 可以匹配空字符串、aaaaaa 等,也就是包含任意多个 a(也可以没有 a)的字符串都能匹配。
  • +:匹配前面的元素一次或多次,如 a+ 会匹配 aaaaaa 等,但不能匹配空字符串,必须至少有一个 a 存在。
  • ?:匹配前面的元素零次或一次,比如 a? 可以匹配空字符串或者 a,有或者没有 a 的情况都能应对。
  • {n}:匹配前面的元素恰好 n 次,例如 a{3} 只会匹配 aaa 这样刚好连续出现三次 a 的字符串。
  • {n,m}:匹配前面的元素至少 n 次且最多 m 次,像 a{1,3} 可以匹配 aaaaaa,也就是 a 的数量在 1 到 3 个之间的字符串都符合要求。
边界匹配符
  • ^:匹配字符串的开头,当它位于正则表达式开头时,表示要从目标文本的开头去匹配相应模式,例如 ^abc 只会匹配以 abc 开头的字符串,像 abcdef 能匹配,而 defabc 就不能匹配。
  • $:匹配字符串的结尾,例如 xyz$ 只会匹配以 xyz 结尾的字符串,像 abcxyz 能匹配,xyzabc 则不行。
分组与引用
  • ( ):用于分组,将括号内的内容作为一个整体进行处理,比如在匹配电话号码时,可能会写成 (\d{3})-(\d{4})-(\d{4}),这里把区号、电话号码的前四位和后四位分别进行了分组,方便后续提取匹配到的各个部分,也可以在正则表达式内部对分组进行引用等操作(不同编程语言实现方式略有不同)。
其他常用符号
  • .:匹配除换行符 \n 以外的任意一个字符,例如 a.c 可以匹配 abcaaca#c 等任何中间是一个任意字符的字符串。
  • |:逻辑或运算符,表示匹配它两边的表达式中的任意一个,例如 abc|def 可以匹配 abc 或者 def
断言 
  • 正向断言,正则在前,条件在后

  • 反向断言: 条件在前,正则在后

  • 正向确定断言:rex(?=\d+) 提取后面是数字的rex

  • 正向否定断言:rex(?!\d+) 提取后面不是数字的rex

  • 反向确定断言:(?<=window)\d+ 提取前面是window的数字

  • 反向否定断言:(?<!window)\d+ 提取前面不是window的数字 (?=.*rex):某个字符串必须包含rex

 练习
 # 手机号  ^1[3-9]\d{9}$

 # 10-12  ^1[0-2]$
 # 0-12   ^(\d|1[0-2])$
    0-9  \d
    10-12  1[0-2]

 # 0-255   ^(\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])$
    0-9        \d
    10-99     [1-9]\d
    100-199   1\d{2}
    200-249   2[0-4]\d
    250-255   25[0-5]

 # 匹配 ipv4地址
  ^(\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])(\.(\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])){3}$
   0-255.0-255.0-255.0-255

 # 必须有大写字母  小写字母  数字  6-8位
 ^(?=.*\d)(?=.*[A-Z])(?=.*[a-z])[A-Za-z0-9]{6,8}$

 

3. Python 中 re 模块的使用

匹配操作
  • re.match():从字符串的开头开始匹配,如果开头不符合正则表达式模式,则匹配失败,返回 None,只有当开头匹配成功时,才会返回一个匹配对象。例如:
import re

"""
re.match(pattern, string, flags=0)
 pattern:匹配正则
 string: 匹配的字符串
 flags:匹配模式
 匹配以 pattern 开头的 子串  ,返回match对象
 函数:
    group(): 获取最终匹配子串结果
    groups():获取分组结果组成的元组
    group(index):获取指定索引分组结果
    group(name):获取指定名称分组结果
    span(): 获取匹配到的子串的首尾下标
"""
s = '1223ab'
res = re.match(r'(\d{2})(\d{2})', s)
print(res)
print(res.group())  # 12
print(res.span())  # (0, 2)
print(res.start())  # 0
print(res.end())  # 2
print(res.groups())

# 匹配以 pattern 开头的  以pattern结尾 子串  ,返回match对象
s = '1223'
res = re.fullmatch(r'(\d{2})(\d{2})', s)
print(res)
print(res.group())  # 1223
  • re.search():在整个字符串中查找是否存在符合正则表达式模式的部分,只要字符串中有一处匹配成功,就返回一个匹配对象,若整个字符串都没有符合模式的部分,则返回 None。例如:
import re

'''
  search(pattern, string,flag)
  search:匹配符合条件第一个子串和首尾下标,
  返回match对象,找不到返回None
  
  index(''):返回第一个下标,找不到报错
  find(''):返回第一个下标,找不到-1
'''
s = 'a12b23'
res = re.search(r'\d{2}', s)
print(res)

'''
search(pattern, string,flag)
  finditer:匹配符合条件所有子串,返回迭代器
  迭代器中每一个元素是match对象
'''
s = 'a12b23'
res = re.finditer(r'\d{2}', s)
for r in res:
    print(r.group())
  • re.findall():在整个字符串中查找所有符合正则表达式模式的子串,并以列表形式返回这些子串。例如:

import re
'''
   findall(pattern,string,flag)
   如果没有分组:返回匹配子串组成的列表
   如果有一个分组:只返回分组结果组成的列表
   如果有多个分组:返回分组元祖组成的列表
   总结:
     如果有分组,findall只返回分组结果
'''
s = '13067895786'
res = re.findall(r'(\d{3})(\d{4})\d{4}', s)
print(res)

# 提取身份证号的 出生年  月  日
s = '41072419980815451x'
res = re.findall(r'\d{6}(\d{4})(\d{2})(\d{2})', s)
print(res[0])

# 30岁,25个 ,95年=》30,25,95
s = '30岁,25个 ,95年'
res = re.findall(r'\d+', s)
print(res)

'''
假设我们有一些’username@companyname.com'格式的电子邮件地址,
请编写程序打印给定电子邮件地址的用户名,用户名和公司名都只由字母组成
如果下面的电子邮件地址作为程序的输入:john@google.com.
那么程序的输出应该是:john
'''
s = 'john@google.com'
res = re.findall(r'(\w+)@', s)
print(res)

'''
insert into tb_user(name, sex, age) 
values ( #{name} , #{sex} , #{age} )
提取 #{name} , #{sex} , #{age}
'''
s = 'insert into tb_user(name, sex, age) values ( #{name} , #{sex} , #{age} )'
res = re.findall(r'#{\w+}', s)
print(res)

# asb13345672234fgfg156345245778dshh, 提取所有手机号
#  [('13345672234', '133', '4567'), ('15634524577', '156', '3452')]
s = 'asb13345672234fgfg156345245778dshh'
res = re.findall(r'((\d{3})(\d{4})\d{4})', s)
print(res)
替换操作

        使用 re.sub() 函数可以根据正则表达式模式来替换字符串中的相应部分,它接收三个主要参数,第一个是正则表达式模式,第二个是用于替换的字符串,第三个是要被操作的原始字符串。例如:

'''
   match(pattern,string,flags):以pattern开头,返回match对象
   fullmatch(pattern,string,flags):以pattern开头,以pattern结尾,返回match对象
   finditer(pattern,string,flags): 符合pattern的所有结果,返回迭代器,迭代器的元素放的是match对象
   search(pattern,string,flags):符合pattern的第一个数据,,返回match对象

   findall(pattern,string,flags):
       没有分组: 返回所有匹配结果组成的列表
       如果有1个分组: 只返回这1个分组结果组成的列表
       如果有多个分组: 只返回多个分组结果元组组成的列表
   sub(pattern,repl,string,count,flags):
     返回替换后的结果
     pattern:被替换的正则
     repl:
       要替换的正则或字符串或lamda,lamda 参数为匹配结果
       如果使用反向引用,必须 使用  r'\1***\2'
     count:替换个数
   subn(pattern,repl,string,count,flags):
   返回替换后的结果和替换个数 组成的元组
   re.split(pattern,string,maxsplit,flags)
   按照pattern拆分,返回拆分后的列表
   字符串替换:
     replace(old,new,string,count)
     old:被替换的子串
     new:要替换的字串
     count:替换的个数

'''
import re

# 替换所有数字为#
s = 'he12llow wo34rld11'
res = re.sub(r'\d+', '#', s, count=2)
print(res)

# 手机号脱敏 165****3768
s = '16586983768'
res = re.sub(r'(\d{3})\d{4}(\d{4})', r'\1****\2', s)
print(res)

# 邮箱脱敏 h*******@163.com
s = 'henanzhengzhou@163.com'
res = re.sub(r'(.).+(@.+)', r'\1*******\2', s)
print(res)

# 将所有数字 翻转替换
s = 'he123llow wo456rld'
res = re.sub(r'\d+', lambda x: (x.group())[::-1], s)
print(res)

s = 'he12llow wo34rld11'
res = re.subn(r'\d+', '#', s)
print(res)  # ('he#llow wo#rld#', 3)

s = 'hello11world22qiku'
res = re.split(r'\d+', s)
print(res)  # ['hello', 'world', 'qiku']

# 先创建正则对象
# pattern = re.compile(r'\d+')
# m = pattern.match('12twothree34four')
# print(m)
分割操作

re.split() 函数依据正则表达式模式来分割字符串,它返回分割后的字符串列表。例如:

import re

pattern = r",|\s"  # 以逗号或者空白字符作为分割依据
text = "apple, banana  cherry"
result = re.split(pattern, text)
print(result)

运行后输出 ['apple', 'banana', 'cherry'],也就是按照指定的模式将原字符串进行了分割。

正则表达式功能强大,但语法相对复杂,需要通过不断练习和实际应用才能熟练掌握,以便在文本处理、数据验证、信息提取等众多场景中发挥作用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值