正则表达式先入门,精不精通看修行

1.元字符

元字符是构造正则表达式的一种基本元素,可以匹配一个或多个字符,或者根据特定的规则进行匹配。

元字符

说明

.匹配除换行符以外的任意字符
\w匹配字母或数字或下划线或汉字
\s匹配任意的空白符
\d匹配数字
\b匹配单词的开始或结束
^匹配字符串的开始
$匹配字符串结束
匹配有abc开头的字符串:
\babc或者^abc

匹配8位数字的QQ号码:
^\d\d\d\d\d\d\d\d$

匹配1开头11位数字的手机号码:
^1\d\d\d\d\d\d\d\d\d\d$

2.重复限定符

正则表达式中一些重复限定符,把重复部分用合适的限定符替代。

语法说明
*重复零次或更多次
+重复一次或更多次
?重复零次或一次
{n}重复n次
{n,}重复n次或更多次
{n,m}重复n到m次
匹配8位数字的QQ号码:
 ^\d{8}$

匹配1开头11位数字的手机号码:
^1\d{10}$

匹配银行卡号是14~18位的数字:
^\d{14,18}$

匹配以a开头的,0个或多个b结尾的字符串
^ab*$

3.分组

从上面的例子中看到,限定符是作用在与他左边最近的一个字符,那么问题来了,如果我想要 ab 同时被限定那怎么办呢?

正则表达式中用小括号 () 来做分组,也就是括号中的内容作为一个整体。

匹配字符串中包含 0 到多个 ab 开头:

^(ab)*

4.转义

我们看到正则表达式用小括号来做分组,那么问题来了:

如果要匹配的字符串中本身就包含小括号,那是不是冲突?应该怎么办?

针对这种情况,正则提供了转义的方式,也就是要把这些元字符、限定符或者关键字转义成普通的字符,做法很简答,就是在要转义的字符前面加个斜杠,也就是\即可。

例如,要匹配以 (ab) 开头:
 ^(\(ab\))*

5. 条件或

正则用符号 | 来表示或,也叫做分支条件,当满足正则里的分支条件的任何一种条件时,都会当成是匹配成功。

比如联通有 130/131/132/155/156/185/186/145/176 等号段
假如让我们匹配一个联通的号码,就可以用或条件来处理这个问题

^(130|131|132|155|156|185|186|145|176)\d{8}$

6.区间

正则提供一个元字符中括号 [] 来表示区间条件。

限定 0 到 9 可以写成 [0-9]

限定 A-Z 写成 [A-Z]

限定某些数字 [165]

^(130|131|132|155|156|185|186|145|176)\d{8}$
可以简化为
^((13[0-2])|(15[56])|(18[5-6])|145|176)\d{8}$

7.零宽断言

‌零宽断言‌是正则表达式中的一种方法,用于查找在某些内容之前或之后的东西,但不包括这些内容

本身。它们像\b, ^, $等锚点一样,用于指定一个位置,这个位置应该满足一定的条件(即断言),

因此它们也被称为零宽断言。

正则表达式的先行断言和后行断言一共有 4 种形式:

  • (?=pattern) 零宽正向先行断言
  • (?!pattern) 零宽负向先行断言
  • (?<=pattern) 零宽正向后行断言
  • (?<!pattern) 零宽负向后行断言

概念说明

  • 正向(Positive): 匹配括号中的表达式,即断言所作的条件判断是肯定的,即只有当条件成立时,匹配才成功。
  • 负向(Negative): 不匹配括号中的表达式,即​断言所作的条件判断是否定的,即只有当条件不成立时,匹配才成功。
  • 先行(Lookahead): 表示断言发生在匹配位置之前。
  • 后行(Lookbehind): 表示断言发生在匹配位置之后。

假设我们要用爬虫抓取 csdn 里的文章阅读量。通过查看源代码可以看到文章阅读量这个内容是这样的结构。

"<span class="read-count">阅读数:641</span>"

要取到阅读量,在正则表达式中就意味着要能匹配到‘</span>’前面的数字内容,按照上所说的正

向先行断言可以匹配表达式前面的内容。

import re

# 定义正则表达式和测试文本
reg = r".+(?=</span>)"
test = "<span class=\"read-count\">阅读数:641</span>"

print("文本:" + test)
print("正则表达式:" + reg)

# 编译正则表达式
pattern = re.compile(reg)

# 创建匹配器
mc = pattern.finditer(test)

# 遍历所有匹配项
for match in mc:
    print("匹配结果:")
    print(match.group())


运行结果:
文本:<span class="read-count">阅读数:641</span>
正则表达式:.+(?=</span>)
匹配结果:
<span class="read-count">阅读数:641

如果只要数字,那么匹配数字 \d, 那可以改成:

import re

# 定义正则表达式和测试文本
reg = r"\d+(?=</span>)"
test = "<span class=\"read-count\">阅读数:641</span>"

print("文本:" + test)
print("正则表达式:" + reg)

# 编译正则表达式
pattern = re.compile(reg)

# 创建匹配器
mc = pattern.finditer(test)

# 遍历所有匹配项
for match in mc:
    print(match.group())

//匹配结果:
//641

先行是匹配前面的内容,那后行就是匹配后面的内容啦。可以用后行断言来处理:

import re

# 定义正则表达式和测试文本
reg = r"(?<=<span class=\"read-count\">阅读数:)\d+"
test = "<span class=\"read-count\">阅读数:641</span>"

print("文本:" + test)
print("正则表达式:" + reg)

# 编译正则表达式
pattern = re.compile(reg)

# 创建匹配器
mc = pattern.finditer(test)

# 遍历所有匹配项
for match in mc:
    print(match.group())


输出结果:
文本:<span class="read-count">阅读数:641</span>
正则表达式:(?<=<span class="read-count">阅读数:)\d+
641

8.捕获与非捕获组

捕获通常和分组联系在一起,也就是“捕获组”。捕获组通过圆括号() 来标识,能够在匹配时将括号

内的内容单独保存,并在后续处理中提取或引用。捕获组的出现是为了简化复杂模式的匹配,并方

便从文本中提取关键信息,如提取日期、邮箱、URL 等。

在正则表达式中,通过将部分模式用圆括号括起来,形成一个捕获组。

每个捕获组会分配一个组号,从左到右依次编号,最左边的组为第一个,编号为 1

编号为 0 的组总是指整个正则表达式匹配的内容。

通过这些组号,匹配到子字符串可以在后续处理中被引用和操作。

而根据命名方式的不同,又可以分为两种组:

1.数字编号捕获组:

语法:(exp)

解释:从表达式左侧开始,每出现一个左括号和它对应的右括号之间的内容为一个分组,在分组中,第 0 组为整个表达式,第一组开始为分组。

比如固定电话的:020-85653333

他的正则表达式为:(0\d{2})-(\d{8})

按照左括号的顺序,这个表达式有如下分组:

序号编号分组内容
00(0\d{2})-(\d{8})020-85653333
11(0\d{2})020
22(\d{8})85653333

2.命名编号捕获组

语法:(?<name>exp)

解释:分组的命名由表达式中的 name 指定

比如区号也可以这样写:(?<quhao>\0\d{2})-(?<haoma>\d{8}),按照左括号的顺序,这个表达式有如下分组:

序号名称分组内容
00(0\d{2})-(\d{8})020-85653333
1quhao(0\d{2})020
2haoma(\d{8})85653333

非捕获组

语法:(?:exp)

它不捕获文本 ,也不针对组合计进行计数。比如上面的正则表达式,程序不需要用到第一个分组,那就可以这样写:

(?:\0\d{2})-(\d{8})
序号编号分组内容
00(0\d{2})-(\d{8})020-85653333
11(\d{8})85653333

9.反向组

捕获会返回一个捕获组,这个分组是保存在内存中,不仅可以在正则表达式外部通过程序进行引

用,也可以在正则表达式内部进行引用,这种引用方式就是反向引用。它的作用主要是用来查找一

些重复的内容或者做替换指定字符。

正则表达式的匹配是从左到右进行的。当遇到反向引用时,会尝试用之前捕获组匹配到的内容去替

换当前位置,如果替换后能够继续匹配,则继续;否则,匹配失败。

根据捕获组的命名规则,反向引用可分为:

  • 数字编号组反向引用:\k 或\number

  • 命名编号组反向引用:\k 或者\'name'

例如,找一串字母"aabbbbgbddesddfiid"里成对的字母

思路:

1)匹配到一个字母

2)匹配第下一个字母,检查是否和上一个字母是否一样

3)如果一样,则匹配成功,否则失败

首先匹配一个字母:\w,我们需要做成分组才能捕获,因此写成这样:(\w)

那这个表达式就有一个捕获组:(\w)

然后我们要用这个捕获组作为条件,那就可以:(\w)\1这样就大功告成了。

捕获组和反向引用的工作原理

  1. 捕获组 (\\w)

    • 每次 \\w 匹配到一个字符时,这个字符会被捕获到一个组中。这个组的编号为1。

    • 捕获组的内容是动态的,每次匹配到新的字符时,组中的内容会被更新。

  2. 反向引用 \\1

    • \\1 会匹配与第一个捕获组(即 \\w)相同的字符。

    • 每次 \\w 匹配到新的字符时,\\1 会匹配与这个新字符相同的下一个字符。

  • 字符串: aabbbbgbddesddfiid

  • 匹配过程:

    • aa:第一个 \\w 匹配 a,捕获到组1中,\\1 匹配 a,输出 aa

    • bb:第一个 \\w 匹配 b,捕获到组1中,\\1 匹配 b,输出 bb

    • bb:第一个 \\w 匹配 b,捕获到组1中,\\1 匹配 b,输出 bb

    • bb:第一个 \\w 匹配 b,捕获到组1中,\\1 匹配 b,输出 bb

    • dd:第一个 \\w 匹配 d,捕获到组1中,\\1 匹配 d,输出 dd

    • dd:第一个 \\w 匹配 d,捕获到组1中,\\1 匹配 d,输出 dd

    • ii:第一个 \\w 匹配 i,捕获到组1中,\\1 匹配 i,输出 ii

import re

# 待匹配的字符串
text = 'aabbbbgbddesddfiid'

# 正则表达式,匹配连续的相同字符对
pattern = r'(\w)\1'

# 使用re模块的findall方法查找所有匹配的字符对
matches = re.findall(pattern, text)

# 输出匹配结果
for match in matches:
    print(match + match)  # 输出连续的相同字符对

10.贪婪与非贪婪

在正则表达式中,贪婪(greedy)和非贪婪(non-greedy)是两种不同的匹配模式,它们决定了正

则表达式在匹配字符串时的行为。贪婪模式是正则表达式的默认匹配模式。在这种模式下,正则表

达式会尽可能多地匹配字符。非贪婪模式(也称为懒惰模式)与贪婪模式相反。在这种模式下,正

则表达式会尽可能少地匹配字符。

前面我们讲过重复限定符,其实这些限定符就是贪婪量词,比如表达式\d{3,6}:

文本:61762828 176 2991 871
贪婪模式:\\d{3,6}
匹配结果:617628
匹配结果:176
匹配结果:2991
匹配结果:871

贪婪模式:正则表达式 \d{3,6} 会尽可能多地匹配字符,但不会超过6位。
匹配结果:匹配所有长度在3到6位之间的数字。

匹配 61762828
正则表达式 \d{3,6} 从字符串的开头开始匹配。
它会尽可能多地匹配数字,但不会超过6位。
因此,它匹配了前6位数字 617628

匹配过的字符不会再参与后续的匹配。
正则表达式引擎在找到一个匹配后,会从匹配结束的位置继续查找下一个匹配
不会重新考虑已经匹配过的字符

 当多个贪婪量词在一起时,正则表达式引擎会按照从左到右的顺序进行匹配,每个量词都会尽可

能多地匹配字符,但会受到其他量词和整个正则表达式的约束。如果某个量词的贪婪匹配导致后续

部分无法匹配成功,正则表达式引擎会进行回溯,尝试减少当前量词的匹配长度,以便后续部分能

够成功匹配。

示例

假设我们有字符串 abcde12345,要匹配的正则表达式是 (.*)(\d+)

  1. 初始贪婪匹配

    • (.*) 是一个贪婪量词,它会尽可能多地匹配字符。在匹配字符串 abcde12345 时,它会先匹配整个字符串,即 abcde12345

    • \d+ 也表示贪婪匹配一个或多个数字,但由于前面的 (.*) 已经匹配了整个字符串,此时 \d+ 无法再匹配到数字,因为已经没有剩余的字符了。

  2. 回溯过程

    • 正则表达式引擎发现(\d+)无法匹配,于是开始回溯。它会减少 (.*) 的匹配长度,尝试让后续的 (\d+)能够匹配成功。

    • (.*) 先减少一个字符,匹配 abcde1234,此时 (\d+) 可以匹配到数字 5,匹配成功。所以最终匹配结果是 abcde1234(.*) 匹配,5(\d+) 匹配。

import re

# 待匹配的字符串
text = 'abcde12345'

# 正则表达式,将\d+部分也用圆括号括起来,使其成为一个捕获组
pattern = r'(.*)(\d+)'

# 使用re模块的search方法进行匹配
match = re.search(pattern, text)

if match:
    # 输出匹配结果
    print("匹配成功!")
    print("正则表达式:" + pattern)
    print("匹配的整个字符串为:", match.group(0))
    print("第一个捕获组匹配的内容为:", match.group(1))
    print("第二个捕获组匹配的内容为:", match.group(2))
else:
    print("匹配失败!")


输出结果:
匹配成功!
正则表达式:(.*)(\d+)
匹配的整个字符串为: abcde12345
第一个捕获组匹配的内容为: abcde1234
第二个捕获组匹配的内容为: 5

 懒惰(非贪婪)

懒惰(非贪婪)量词在正则表达式中用于尽可能少地匹配字符。与贪婪量词相反,懒惰量词会尝试

匹配最少的字符,以满足整个正则表达式的匹配条件。懒惰量词通常通过在量词后面加上一个问号

? 来表示。

代码说明
*?重复任意次,但尽可能少重复
+?重复1次或更多次,但尽可能少重复
??重复0次或1次,但尽可能少重复
{n,m}?重复n到m次,但尽可能少重复
{n,}?重复n次以上,但尽可能少重复
假设我们有字符串 "abc123def456",使用正则表达式 (\w+?)(\d+):
(\w+?):懒惰模式,匹配一个或多个字母、数字或下划线,但尽可能少。
(\d+):贪婪模式,匹配一个或多个数字。


匹配过程
从文本“abc123def456”开始,正则表达式首先尝试用(\\w+?)匹配。
它匹配“abc”,因为“abc”是第一个字母序列,且非贪婪匹配使得它在这里停止。
接下来,正则表达式用(\\d+)匹配。在“abc”之后,它匹配“123”,因为“123”是第一个数字序列。

import re

# 定义正则表达式和测试文本
reg = r"(\w+?)(\d+)"
test = "abc123def456"

print("文本:" + test)
print("正则表达式:" + reg)

# 编译正则表达式
p1 = re.compile(reg)

# 创建匹配器
m1 = p1.search(test)

if m1:
    print("匹配结果:")
    print("整个匹配:" + m1.group(0))
    print("部分1:" + m1.group(1))
    print("部分2:" + m1.group(2))
else:
    print("没有匹配到任何内容")

运行结果:
文本:abc123def456
正则表达式:(\w+?)(\d+)
匹配结果:
整个匹配:abc123
部分1:abc
部分2:123

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/955348.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

高等数学学习笔记 ☞ 不定积分的积分方法

1. 第一换元积分法 1. 基础概念&#xff1a;形如的过程&#xff0c;称为第一换元积分法。 2. 核心思想&#xff1a;通过对被积函数的观察(把被积函数的形式与积分表的积分公式进行比较)&#xff0c;把外部的部分项拿到的内部(求原函数)&#xff0c; 然后进行拼凑&#xff0c;…

win32汇编环境,窗口程序中基础列表框的应用举例

;运行效果 ;win32汇编环境,窗口程序中基础列表框的应用举例 ;比如在窗口程序中生成列表框&#xff0c;增加子项&#xff0c;删除某项&#xff0c;取得指定项内容等 ;直接抄进RadAsm可编译运行。重点部分加备注。 ;以下是ASM文件 ;>>>>>>>>>>>…

Jmeter配置服务代理器 Proxy(二)

1.创建脚本记录器 2.配置&#xff1a;Jmeter代理、端口、记录目标等 3.配置谷歌浏览器代理 浏览器配置代理的详细教程可参考&#xff1a;使用whistle代理-CSDN博客 4.启动Jmeter记录器 点击ok后弹出这个界面&#xff0c;生成了证书&#xff1a; 5.给浏览器安装Jmeter代理的证书…

红日-VulnStack靶场一

http://vulnstack.qiyuanxuetang.net/vuln/ 一、环境部署 win7(被攻击机/关火墙) web服务器 1张外网网卡(桥接192.168.1.105)&#xff0c;一张内网网卡192.168.52.143/255.255.255.0/192.168.52.2 DNS 192.168.52.138 winser2008 域控服务器 1张…

Chrome谷歌浏览器如何能恢复到之前的旧版本

升级了谷歌最新版不习惯&#xff0c;如何降级版本 未完待续。。 电脑中的Chrome谷歌浏览器升级到了最新版本&#xff0c;但是有种种的不适应&#xff0c;如何能恢复到之前的旧版本呢&#xff1f;我们来看看操作步骤&#xff0c;而且无需卸载重装。 怎么恢复Chrome 之前版本&a…

云上贵州多彩宝荣获仓颉社区先锋应用奖 | 助力数字政务新突破

在信息技术应用创新的浪潮中&#xff0c;仓颉社区吸引了众多企业和开发者的积极参与&#xff0c;已有多个应用成功落地&#xff0c;展现出蓬勃的创新活力。仓颉编程语言精心遴选了在社区建设、应用创新、开源共建、技术布道等方面做出突出贡献的优秀项目应用&#xff0c;并颁发…

LabVIEW实车四轮轮速信号再现系统

开发了一个基于LabVIEW的实车四轮轮速信号再现系统。该系统解决现有电机驱动传感器成本高、重复性差、真实性差和精度低等问题&#xff0c;提供一种高精度、低成本的轮速信号再现解决方案。 项目背景 ABS轮速传感器在现代汽车安全系统中发挥着至关重要的作用。为保证其准确性和…

Java算法 二叉树入门 力扣简单题相同的树 翻转二叉树 判断对称二叉树 递归求二叉树的层数

目录 模版 先序遍历 中序遍历 后序遍历 力扣原题 相同的二叉树 力扣原题 翻转二叉树 遍历树的层数 题目 静态变量 核心逻辑 模版 // 二叉树public static class Node{public int value;public Node left;public Node right;public Node(int v) {valuev;}} 先序遍历 …

P6周:VGG-16算法-Pytorch实现人脸识别

&#x1f368; 本文为&#x1f517;365天深度学习训练营中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 我的环境 语言环境&#xff1a;Python 3.8.12 编译器&#xff1a;jupyter notebook 深度学习环境&#xff1a;torch 1.12.0cu113 一、前期准备 1.设置GPU im…

Ubuntu、Windows系统网络设置(ping通内外网)

一、 虚拟机VMware和Ubuntu系统的网络配置说明 1、虚拟机的网络适配器的模式有三种&#xff1a; 桥接模式NAT模式主机模式 2、虚拟机VMware的网卡配置(如何进行配置界面(虚拟机->设置)) 注意&#xff1a; 1、以上桥接模式(ubuntu有独立IP)、NAT模式(没有独立IP)都可以联…

Web端实时播放RTSP视频流(监控)

一、安装ffmpeg: 1、官网下载FFmpeg: Download FFmpeg 2、点击Windows图标,选第一个:Windows builds from gyan.dev 3、跳转到下载页面: 4、下载后放到合适的位置,不用安装,解压即可: 5、配置path 复制解压后的\bin路径,配置环境变量如图: <

Mongodb相关内容

Mongodb相关内容 1、Windows平台安装2、Linux平台安装3、基本常用命令文档更新删除文档分页查询索引 pymongo操作 客户端下载&#xff1a;https://download.csdn.net/download/guoqingru0311/90273435 1、Windows平台安装 方式一&#xff1a; 方式2&#xff1a; 方式3&#…

SQL2000在win10上安装的方法

安装前最好先关闭防火墙和一些杀毒软件&#xff0c;因为这些软件在安装过程中可能会碰到注册表等一下杀毒软件比较敏感的地带&#xff0c;如果违反杀毒软件的规则会被当做病毒强行终止删除 首相找到C盘下window文件中的sysWOW64文件 鼠标右键&#xff0c;点击属性、安全、高级 …

EAMM: 通过基于音频的情感感知运动模型实现的一次性情感对话人脸合成

EAMM: 通过基于音频的情感感知运动模型实现的一次性情感对话人脸合成 1所有的材料都可以在EAMM: One-Shot Emotional Talking Face via Audio-Based Emotion-Aware Motion Model网站上找到。 摘要 尽管音频驱动的对话人脸生成技术已取得显著进展&#xff0c;但现有方法要么忽…

【华为路由/交换机的ftp文件操作】

华为路由/交换机的ftp文件操作 PC&#xff1a;10.0.1.1 R1&#xff1a;10.0.1.254 / 10.0.2.254 FTP&#xff1a;10.0.2.1 S1&#xff1a;无配置 在桌面创建FTP-Huawei文件夹&#xff0c;里面创建config/test.txt。 点击上图中的“启动”按钮。 然后ftp到server&#xff0c;…

Web前端开发技术之HTMLCSS知识点总结

学习路线 一、新闻网界面1. 代码示例2. 效果展示3. 知识点总结3.1 HTML标签和字符实体3.2 超链接、颜色描述与标题元素3.3 关于图片和视频标签&#xff1a;3.4 CSS引入方式3.5 CSS选择器优先级 二、flex布局1. 代码示例2. 效果展示3. 知识点总结3.1 span标签和flex容器的区别3.…

基于SSM汽车美容管家【提供源码+答辩PPT+文档+项目部署】(高质量源码,可定制,提供文档,免费部署到本地)

作者简介&#xff1a;✌CSDN新星计划导师、Java领域优质创作者、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和学生毕业项目实战,高校老师/讲师/同行前辈交流。✌ 主要内容&#xff1a;&#x1f31f;Java项目、Python项目、前端项目、PHP、ASP.NET、人工智能…

idea gradle compiler error: package xxx does not exist

idea 编译运行task时报项目内的包不存在&#xff0c;如果你试了网上的其它方法还不能解决&#xff0c;应该是你更新了新版idea&#xff0c;项目用的是旧版jdk&#xff0c;请在以下编译器设置中把项目JDK字节码版本设为8&#xff08;jdk1.8&#xff0c;我这里是17请自行选择&…

1.17学习

crypto nssctf-[SWPUCTF 2021 新生赛]crypto8 不太认识这是什么编码&#xff0c;搜索一下发现是一个UUENCODE编码&#xff0c;用在线工具UUENCODE解码计算器—LZL在线工具解码就好 misc buuctf-文件中的秘密 下载附件打开后发现是一个图片&#xff0c;应该是一个图片隐写&…

Formality:参考设计/实现设计以及顶层设计

相关阅读 Formalityhttps://blog.csdn.net/weixin_45791458/category_12841971.html?spm1001.2014.3001.5482​​​ Formality存在两个重要的概念&#xff1a;参考设计/实现设计和顶层设计&#xff0c;本文就将对此进行详细阐述。参考设计/实现设计是中两个重要的全局概念&am…