匹配分组

字符功能
|匹配左右任意一个表达式
(ab)将括号中字符作为一个分组
\num引用分组num匹配到的字符串
(?P<name>)分组起别名
(?P=name)引用别名为name分组匹配到的字符串

示例1:|

需求:匹配出0-100之间的数字

#coding=utf-8

import re

ret = re.match("[1-9]?\d","8")
print(ret.group())  # 8

ret = re.match("[1-9]?\d","78")
print(ret.group())  # 78

# 不正确的情况
ret = re.match("[1-9]?\d","08")
print(ret.group())  # 0

# 修正之后的
ret = re.match("[1-9]?\d$","08")
if ret:
    print(ret.group())
else:
    print("不在0-100之间")

# 添加|
ret = re.match("[1-9]?\d$|100","8")
print(ret.group())  # 8

ret = re.match("[1-9]?\d$|100","78")
print(ret.group())  # 78

ret = re.match("[1-9]?\d$|100","08")
# print(ret.group())  # 不是0-100之间

ret = re.match("[1-9]?\d$|100","100")
print(ret.group())  # 100

示例2:( )

需求:匹配出163、126、qq邮箱

#coding=utf-8

import re

ret = re.match("\w{4,20}@163\.com", "test@163.com")
print(ret.group())  # test@163.com

ret = re.match("\w{4,20}@(163|126|qq)\.com", "test@126.com")
print(ret.group())  # test@126.com

ret = re.match("\w{4,20}@(163|126|qq)\.com", "test@qq.com")
print(ret.group())  # test@qq.com

ret = re.match("\w{4,20}@(163|126|qq)\.com", "test@gmail.com")
if ret:
    print(ret.group())
else:
    print("不是163、126、qq邮箱")  # 不是163、126、qq邮箱

不是以4、7结尾的手机号码(11位)

import re

tels = ["13100001234", "18912344321", "10086", "18800007777"]

for tel in tels:
    ret = re.match("1\d{9}[0-35-68-9]", tel)
    if ret:
        print(ret.group())
    else:
        print("%s 不是想要的手机号" % tel)

提取区号和电话号码

>>> ret = re.match("([^-]*)-(\d+)","010-12345678")
>>> ret.group()
'010-12345678'
>>> ret.group(1)
'010'
>>> ret.group(2)
'12345678'

示例3:\

需求:匹配出<html>hh</html>

#coding=utf-8

import re

# 能够完成对正确的字符串的匹配
ret = re.match("<[a-zA-Z]*>\w*</[a-zA-Z]*>", "<html>hh</html>")
print(ret.group())

# 如果遇到非正常的html格式字符串,匹配出错
ret = re.match("<[a-zA-Z]*>\w*</[a-zA-Z]*>", "<html>hh</htmlbalabala>")
print(ret.group())

# 正确的理解思路:如果在第一对<>中是什么,按理说在后面的那对<>中就应该是什么

# 通过引用分组中匹配到的数据即可,但是要注意是元字符串,即类似 r""这种格式
ret = re.match(r"<([a-zA-Z]*)>\w*</\1>", "<html>hh</html>")
print(ret.group())

# 因为2对<>中的数据不一致,所以没有匹配出来
test_label = "<html>hh</htmlbalabala>"
ret = re.match(r"<([a-zA-Z]*)>\w*</\1>", test_label)
if ret:
    print(ret.group())
else:
    print("%s 这是一对不正确的标签" % test_label)

运行结果:

<html>hh</html>
<html>hh</htmlbalabala>
<html>hh</html>
<html>hh</htmlbalabala> 这是一对不正确的标签

示例4:\number

需求:匹配出<html><h1>www.itcast.cn</h1></html>

#coding=utf-8

import re

labels = ["<html><h1>www.itcast.cn</h1></html>", "<html><h1>www.itcast.cn</h2></html>"]

for label in labels:
    ret = re.match(r"<(\w*)><(\w*)>.*</\2></\1>", label)
    if ret:
        print("%s 是符合要求的标签" % ret.group())
    else:
        print("%s 不符合要求" % label)

运行结果:

<html><h1>www.itcast.cn</h1></html> 是符合要求的标签
<html><h1>www.itcast.cn</h2></html> 不符合要求

示例5:(?P<name>) (?P=name)

需求:匹配出<html><h1>www.itcast.cn</h1></html>

#coding=utf-8

import re

ret = re.match(r"<(?P<name1>\w*)><(?P<name2>\w*)>.*</(?P=name2)></(?P=name1)>", "<html><h1>www.itcast.cn</h1></html>")
ret.group()

ret = re.match(r"<(?P<name1>\w*)><(?P<name2>\w*)>.*</(?P=name2)></(?P=name1)>", "<html><h1>www.itcast.cn</h2></html>")
ret.group()

注意:(?P<name>)(?P=name)中的字母p大写

运行结果:

转载于:https://www.cnblogs.com/jyue/p/10468690.html

正则表达式中的分组匹配是一种非常强大的功能,可以将一部分模式封装成一个整体,用于捕获特定内容、重复匹配或引用前面的匹配结果。分组匹配主要通过圆括号 `()` 来实现,并结合引用机制来访问或操作这些分组。 ### 分组匹配的基本用法 1. **简单分组** 使用 `(ab)` 可以将 `ab` 作为一个整体进行匹配。例如,正则表达式 `(ab)+` 可以匹配 `ababab`,表示 `ab` 这个组合可以重复多次。 2. **分枝条件** 使用 `|` 可以实现分枝条件,即匹配左边或右边的表达式。例如,正则表达式 `(0\d{2})-\d{8}|0\d{2}-\d{8}` 可以匹配两种格式的电话号码:一种是前面带有区号且没有连字符的格式(如 `01012345678`),另一种是包含连字符的格式(如 `010-12345678`)[^3]。 ### 分组的引用 1. **反向引用** 使用 `\num` 可以引用之前第 `num` 个分组匹配的内容。例如,正则表达式 `(\d{1,3})\.\d{1,3}\.\d{1,3}\.\d{1,3}` 可以用来匹配 IP 地址,其中第一个分组 `(\d{1,3})` 匹配 IP 地址的第一个数字部分,后续的 `\.` 表示匹配点号。如果需要确保 IP 地址的四个部分都相同,可以使用 `\1` 来引用第一个分组的值,例如 `(\d{1,3})(\.\d{1,3}){3}` 并结合其他逻辑验证每个部分是否一致。 2. **命名分组** 使用 `(?P<name>...)` 可以为分组命名,便于后续引用。例如,正则表达式 `(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})` 可以匹配日期格式 `YYYY-MM-DD`,并且可以通过 `(?P=year)`、`(?P=month)` 和 `(?P=day)` 分别引用年、月、日的值[^1]。 ### 在实际工具中的应用 1. **sed 中的分组替换** 在 `sed` 中,可以通过 `\1`、`\2` 等引用分组匹配的内容。例如,以下命令可以将文件中类似 `username_32位哈希值` 的字符串替换为仅保留用户名部分: ```bash sed -ir "s/([a-zA-Z0-9]+)_[a-z0-9]{32}/\1/g" targetFile.txt ``` 这里,`([a-zA-Z0-9]+)` 匹配用户名并将其作为第一个分组,`_[a-z0-9]{32}` 匹配下划线和 32 位哈希值,替换时通过 `\1` 引用用户名部分[^2]。 2. **Go 中的分组匹配** 在 Go 语言中,正则表达式库 `regexp` 支持分组匹配。例如,以下代码展示了如何使用分组匹配提取日期中的年、月、日: ```go package main import ( "fmt" "regexp" ) func main() { re := regexp.MustCompile(`(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})`) match := re.FindStringSubmatch("2023-10-05") for i, name := range re.SubexpNames() { if i != 0 && name != "" { fmt.Printf("%s: %s\n", name, match[i]) } } } ``` 输出结果为: ``` year: 2023 month: 10 day: 05 ``` ### 总结 正则表达式的分组匹配不仅可以帮助我们捕获特定内容,还可以通过反向引用和命名分组提高表达式的灵活性和可读性。在实际应用中,分组匹配广泛用于文本处理、数据提取和格式验证等场景。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值