Python基础 6 - 正则表达式





  大家好,我是技术界的小萌新,今天要和大家分享一些干货。在阅读之前请先点赞👍,给我一点鼓励吧!这对我来说很重要 (*^▽^*)

1、正则表达式概念

  正则表达式,又称规则表达式 (Regular Expression)。指使用单个字符串来描述、匹配某个句法规则的字符串,常用来检索、替换那些符合某个模式(规则)的文本。


2、正则的三个基础方法

  Python 正则表达式,使用 re 模块,并基于 re 模块中的三个基础方法来做正则匹配。

  分别是:matchsearchfindall 三个基础方法。

1) match 方法

  语法: result = re.match(pattern, string, flags = 0): 必须从字符串开头起始位置进行匹配,匹配成功则返回匹配对象字符串,不成功则返回 None从字符串开头只匹配一次 。返回:<re.Match object; span=(1,6),match='python'>,flags 标志位默认为 0,不应用其他匹配规则。

  re.match 返回一个 re.Match 的 object,其中有 start()、end()、span()(span: 范围,跨度)的方法,分别返回匹配字符串的开始位置(序列索引)、结束位置、span 包含开始、结束的元组 (start, end)

import re
str = "1python python sdfds sdfds python"
print(re.match("python", str))

打印:
None

2) search 方法

  搜索整个字符串,从前往后,匹配一个符合匹配(规则)模式的字符串,不局限于只从字符串开头匹配。匹配不到返回 None

import re
str = "df1python python sdfds sdfds python"
print(re.search("python", str))

打印:
<re.Match object; span=(3, 9), match='python'>

3) findall 方法

  返回所有符合匹配模式的字符串,不局限于匹配一次成功结果。匹配成功则返回多个匹配字符串对象的列表,匹配失败则返回 空list []。如果有捕获组 (),则只返回所有捕获组的元组结果,把每个捕获组捕获到的字符串都作为了一个元组对象,除非捕获组只有一个,则返回该组结果为列表

  re.findall() 中若设定了多个捕获组,捕获组均匹配成功时,返回一个嵌套元组。当其中一个捕获组没有捕获到字符串时,则返回为空列表。若彼此为或者的关系,则整体返回多个元组,这几组捕获组字符串作为其中的元素,没捕获到的为空元素。

import re

str = "df1python python instance instance python"
print(re.findall("pydfthon", str))
print(re.findall("python", str))


str = "df1python python instance instance python"
print("只有一个捕获组的结果:", re.findall("(python)", str))
print("只有一个捕获组的结果:", re.findall("(python)|instance", str))

str = "df1python python instance instance python"
print("具有多个捕获组的结果:", re.findall("(python).*(instance)", str))
print("具有多个捕获组的结果:", re.findall("(python).*(instance)(other)", str))
print("具有多个捕获组的结果:", re.findall("(python)|(instance)", str))

打印:
[]
['python', 'python', 'python']
只有一个捕获组的结果: ['python', 'python', 'python']
只有一个捕获组的结果: ['python', 'python', '', '', 'python']
具有多个捕获组的结果: [('python', 'instance')]
具有多个捕获组的结果: []
具有多个捕获组的结果: [('python', ''), ('python', ''), ('', 'instance'), ('', 'instance'), ('python', '')]

3、元字符匹配

  单字符匹配str.findall(r'\d', string)

   str 字符串的 r 标记,表示旁边字符串是原始字符串,视作普通字符即原来字符串内的( \ 斜杆 )转义字符失效,从而让 re 模块内读到 转义符,进行二次转义,让 ‘\d’ 等转义为匹配模式。

\d: digit 数字 \s: space 空格 \w: word 单词。 r: raw string 原始字符串。

\b: border 边界 [^]: 表示对集合内字符取反,不匹配这些字符或范围。

\W: 非单词字符,即匹配特殊字符。

image-20240827112212047

  数量匹配、边界匹配、分组匹配

image-20240827113124257

警告:

{m,n} “,” 逗号后禁止空格出现,戒掉此类习惯:[1, 2, 3]。

r’\d’ = ‘\\d’ 保留 \ 使单字符匹配生效。 --> \d

r’\.’ = ‘\\.’ 保留 \ 使 . 匹配失效。 --> \.

import re

s = 'python 123 @@@ python 123 @@@'
r = 'python.{,5}\\W*python'
print(re.findall(r,s))	

打印:
['python 123 @@@ python']

4、匹配对象方法

  re.findall() 方法无法使用,可以被 match、search 方法使用。

  group(num = 0): 匹配的整个表达式的字符串,group() 可以一次输入多个组号,在这种情况下它将返回一个包含那些组所对应值的元组。用来获取 match、search 查询到的结果。

  groups(): 返回一个包含所有分组字符串的元组,从 1 到 所含的分组号。

Python3 正则表达式 | 菜鸟教程 (runoob.com)

import re, random

def randomize_date():
    # 生成随机年份
    random_year = random.randint(1900, 2100)
    # 生成随机月份
    random_month = random.randint(1, 12)
    # 生成随机日期
    # 注意:这里简单处理,假设每个月都有 31 天
    random_day = random.randint(1, 31)
    # 构建新的随机日期字符串
    random_date_str = f"{random_year:04d}-{random_month:02d}-{random_day:02d}"
    return random_date_str

# t = "2024-08-27"
t = randomize_date()
print("生成的随机日期:",t)
r = r'(\d{4})-(0[1-9]|1[0-2])-(0[1-9]|[1-2]\d|3[0-1])'
print(re.match(r, t))
print("捕获的所有分组的元组元素分别是:\t", re.match(r, t).groups())
print("匹配的所有内容是:\t\t\t\t", re.match(r, t).group())
print("匹配的所有内容是:\t\t\t\t", re.match(r, t).group(0))
print("捕获的第 1 个分组内容是:\t\t",re.match(r, t).group(1))
print("捕获的第 2 个分组内容是:\t\t",re.match(r, t).group(2))
print("捕获的第 3 个分组内容是:\t\t",re.match(r, t).group(3))

生成的随机日期: 1911-12-26
<re.Match object; span=(0, 10), match='1911-12-26'>
捕获的所有分组的元组元素分别是:	 ('1911', '12', '26')
匹配的所有内容是:				 1911-12-26
匹配的所有内容是:				 1911-12-26
捕获的第 1 个分组内容是:		 1911
捕获的第 2 个分组内容是:         12
捕获的第 3 个分组内容是:		 26

  匹配规则中调用分组:

  按顺序,元素被捕获组捕获进行分组后,可以在后续的匹配规则中进行调用,格式为 \1-9,代表前面已经被捕获的捕获组 1-9 的捕获元素。用来做数据清晰很方便。

  分组多了以后不方便记忆,分组也可以起别名,格式:(?P<alias>) ,调用该分组: (?P=alias),如以下示例:

技巧:\w 匹配单词,\W 匹配非单词,[\w\W]* 几乎能匹配所有单词。

import re

con = '<title>this is python3</title>'
print(re.match(r'<title>([\w\W]*)</title>',con).group(0))
print(re.match(r'<title>([\w\W]*)</title>',con).group(1))
print(re.match(r'<(\w+)>([\w\W]*)</\1>', con).group(1))
print(re.match(r'<(?P<tag>\w+)>([\w\W]*)</(?P=tag)>', con).group(1))


打印:

<title>this is python3</title>
this is python3
title
title

5、compile 方法

  编译正则匹配规则,生成一个正则表达式对象,供其他方法使用。一般用于频繁使用同一个正则表达式,格式: res = re.compile(r'pattern',[flags]),则 match 方法这样使用:res.match("string")

flags = re.I 忽略大小写
re.M 进行多行字符串匹配
re.S 匹配换行符等空白字符。

6、split、replace 方法

  split 方法默认按组切割捕获的字符串,也可以自定义字符,返回一个列表,存储被切割的元素,类似系统内置 str.split() 方法,格式:re.split(pattern, string, maxsplit = 0, flags) pattern 为切割的字符串,或分组的匹配模式。maxsplit 默认切割次数为 0 ,即无次数分隔。

  sub 方法可以替换字符串中的匹配项。格式:re.sub(pattern, replace, string, count = 0, flags) replace 为替换的字符串,count 默认为 0,即无次数替换。

import re

t = "2024-08-27"
r = r'(\d{4})-(0[1-9]|1[0-2])-(0[1-9]|[1-2]\d|3[0-1])'
print(t)
print(re.split(r, t))  # 默认按分组切割,会有前后的空格字符元素。
print(re.split('-', t))  # 按指定字符 `-` 切割。
print(re.split('-', t, maxsplit=1))  # 可指定切割次数 maxsplit = 1

print(re.sub('-', '/', t))  # 把 - 替换为 / ,也可制定替换次数 count = 1
print(re.sub('-', '/', t, count=1))

打印:

2024-08-27
['', '2024', '08', '27', '']
['2024', '08', '27']
['2024', '08-27']
2024/08/27
2024/08-27

  sub 其他用例:句尾添加换行符。

import re
s = "you're asking me out.that's so cute.what's your name again?"
print(re.sub(r"([.!?])", r"\1\n", s))

打印:
you're asking me out.
that's so cute.
what's your name again?

  sub 进阶用法:按函数规则修改匹配到的字符或数字,再返回替换。replace 为函数,把经过匹配模式匹配到的字符串<re.Match object> 正则对象传入 replace 位置的函数内,数字字符转换为数字后再经过计算返回为字符串:

import re

# 将匹配的数字乘以 2
def double(matched):
    num = int(matched.group('value'))
    return str(num * 2)


s = '1xx2xx3xx4xx5'
print(re.sub(r'(?P<value>\d+)', double, s))

打印:

2xx4xx6xx8xx10

7、贪婪模式与非贪婪

  贪婪模式指 Python 中的数量匹配词默认是 “贪婪” 的,总是尝试匹配尽可能多的字符,相同的匹配项,总是捕获到最后一个匹配项。非贪婪模式相反,总是匹配尽可能少的字符。在数量匹配词如 *、+、?、{m,n}后加上?即可修改数量匹配词为非贪婪匹配模式。

import re

v = re.match(r'(.+)(\d+-\d+-\d+)', 'This is my tel:133-1234-1234')
print("-------贪婪模式------")
print(v.group(1))
print(v.group(2))
print("------非贪婪模式------")
v = re.match(r'(.+?)(\d+-\d+-\d+)', 'This is my te1:133-1234-1234')
print(v.group(1))
print(v.group(2))

打印:

-------贪婪模式------
This is my tel:13
3-1234-1234
------非贪婪模式------
This is my te1:
133-1234-1234

  文章到这里就结束了,希望我的分享能为你的技术之旅增添一抹亮色。如果你喜欢这篇文章,请点赞收藏支持我,给予我前行的动力!🚀



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值