正则表达式量词与贪婪的使用详解

 更新时间:2021-08-04 16:02:31   作者:佚名   我要评论(0)

目录0.写在前面1.量词2.贪婪模式前传2.1 使用 a+ 进行匹配2.2 使用 a* 进行匹配3.贪婪模式4.非贪婪模式5.独占模式5.1 贪婪匹配过程5.2 非贪婪

0.写在前面

在上一篇文章中,我们学习了正则的一些基础元字符,相信大家都已经忘却的差不多了,可以点击上面的链接再温习下。

今天我们一起来学习下正则中量词的三种匹配模式,贪婪模式、非贪婪模式、独占模式,这些模式会改变正则中量词的匹配行为,是每次贪婪的匹配到更多呢,还是不贪婪见好就收呢,如果不了解这些,我们写出的正则很可能是错误的,甚至会引发严重的线上性能问题。

1.量词

本篇文章所讲的内容和量词关系比较密切,先回顾下:

量词

我们还可以用 {m,n} 的方式来表示 * + ? 这3种元字符:

元字符 同义表示方法 示例
* {0,} ab*
可以匹配
a 或者 abb
+ {1,} ab+
可以匹配
ab 或者 abb
但不能匹配 a
? {0,1} ab?
可以匹配 a 或者 ab
但不能匹配 abb

2.贪婪模式前传

在正则中,表示次数的量词默认是贪婪的,在贪婪模式下,会尽可能最大长度的去匹配目标字符串,我们用正则 a+a* 来匹配字符串 aaabb 测试一下。

2.1 使用 a+ 进行匹配

可以看到只匹配到了1个结果 aaa

a+匹配

对应的 Python 代码如下:

import re

print(re.findall(r'a+', 'aaabb'))

输出:['aaa']

2.2 使用 a* 进行匹配

可以看到匹配到了4个结果,其中还有3个是空字符串

a*匹配.jpg

对应的 Python 代码如下:

import re

print(re.findall(r'a*', 'aaabb'))

输出:['aaa', '', '', '']

为什么会匹配到空字符串呢?因为星号(*)代表匹配0到多次,匹配0次就是空字符串,那前面还有个 aaa 呢,为什么 aaa 之间的空字符串没有被匹配到?

这就引入到了我们今天要讲的,贪婪模式与非贪婪模式,从字面上很好理解,贪婪模式就是尽可能多的匹配,非贪婪模式就是尽可能少的匹配。

3.贪婪模式

一起来分析下上面正则 a* 的匹配过程:

字符串 a a a b b 空字符串
下标 0 1 2 3 4 5

匹配 开始 结束 说明 匹配内容
第一次 0 3 到第一个字母b发现不匹配,输出aaa aaa
第二次 3 3 匹配剩下的bb,发现匹配不上,输出空字符串 空字符串
第三次 4 4 匹配剩下的b,发现匹配不上,输出空字符串 空字符串
第四次 5 5 匹配剩下的空字符串,输出空字符串 空字符串

a* 在匹配字符串 aaabb 时,会尽可能多的把前面的 a 都匹配上,直到第一个字母 b 不满足要求为止,匹配上3个 a,后面每次匹配的都是空字符串。

看到这里,相信你已经对贪婪模式有了更深的印象,贪婪模式的特点就是尽可能进行最大长度匹配,就是有多少要多少,下面我们在一起来看下与它完全相反的匹配模式。

4.非贪婪模式

上面讲完了贪婪模式,贪婪模式是尽可能最大长度匹配,非贪婪模式就是尽可能最小长度匹配,在量词的后面加一个问号(?),就成了非贪婪模式,比如 a*?

非贪婪匹配

对应的 Python 代码如下:

import re

// 贪婪匹配
print(re.findall(r'a*', 'aaabb'))

输出:['aaa', '', '', '']

// 非贪婪匹配
print(re.findall(r'a*?', 'aaabb'))

输出:['', 'a', '', 'a', '', 'a', '', '', '']

学完了贪婪模式与非贪婪模式,你可能会问,我什么情况下会用到呢,下面举个栗子感受下:

贪婪匹配例子

非贪婪匹配例子

需求是查找一段字符串中,所有双引号括起来的内容,上面使用贪婪匹配与非贪婪匹配的对比,差别很明显对吧。

5.独占模式

不管是贪婪模式,还是非贪婪模式,匹配过程中都需要发生回溯才能完成想要的功能,但是在有一些场景,我们不需要回溯,匹配不上直接返回失败就可以了,因此正则匹配中还有另外一种模式,独占模式,它和贪婪模式很像,但匹配过程中不会发生回溯,在一些使用场景中性能会更好。

先来讲讲什么是回溯,再举个栗子,有一个正则表达式和目标字符串,我们分别看下在三种匹配模式下都发生了什么:

5.1 贪婪匹配过程

正则表达式:ab{1,3}c

目标字符串:abbc

在匹配时,b{1,3} 会尽可能长的去匹配目标字符串,匹配完 abb 之后,因为要尽可能长的匹配(3个 b),目标字符串中的c就会匹配不上,这个时候会发生向前回溯,吐出当前字符 c,用正则中的 c 去匹配,匹配成功。

贪婪匹配过程

import regex

print(regex.findall(r'ab{1,3}c', 'abbc'))

输出:['abbc']

5.2 非贪婪匹配过程

正则表达式:ab{1,3}?c

目标字符串:abbc

在匹配时,b{1,3} 会尽可能短的去匹配目标字符串,匹配完 ab 之后,会直接用正则 c 去匹配目标字符串剩下的 b,匹配不上,发生向前回溯,重新用正则 b{1,3} 匹配 目标字符串剩下的 b,然后正则 c 匹配 目标字符串剩下的 c,匹配成功。

非贪婪匹配过程

import regex

print(regex.findall(r'ab{1,3}?c', 'abbc'))

输出:['abbc']

5.3 独占匹配过程

在量词后面加上 + 就是独占模式。

正则表达式:ab{1,2}+bc

目标字符串:abbc

在匹配时,b{1,2} 会尽可能长的去匹配目标字符串,匹配完 abb 之后,会用正则 b 匹配目标字符串剩下的 c,匹配不上,不回溯,匹配失败。

独占匹配过程

import regex

print(regex.findall(r'ab{1,2}+bc', 'abbc'))

输出:[]

6.写在最后

最后在总结下上面讲到的内容:

思维导图

到这里,正则表达式的量词与贪婪就讲完了,如果有问题可以给我留言评论,谢谢。

正则表达式在线校验工具:https://regex101.com/

到此这篇关于正则表达式量词与贪婪的使用详解的文章就介绍到这了,更多相关正则表达式 量词与贪婪内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
  • 正则表达式之 贪婪与非贪婪模式详解(概述)
  • 正则表达式(regex) 贪婪模式、懒惰模式使用方法
  • 小议正则表达式效率 贪婪、非贪婪与回溯
  • 浅谈php正则表达式中的非贪婪模式匹配的使用
  • [正则表达式]贪婪模式与非贪婪模式

相关文章

  • 正则表达式量词与贪婪的使用详解

    正则表达式量词与贪婪的使用详解

    目录0.写在前面1.量词2.贪婪模式前传2.1 使用 a+ 进行匹配2.2 使用 a* 进行匹配3.贪婪模式4.非贪婪模式5.独占模式5.1 贪婪匹配过程5.2 非贪婪
    2021-08-04
  • 正则表达式分组与引用的使用

    正则表达式分组与引用的使用

    目录0.写在前面1.分组与编号2.不保存子组3.分组引用4.查找与替换 查找替换5.在文本编辑器中使用查找替换6.写在最后0.写在前面 今天我们来讲下
    2021-08-04
  • 正则表达式常见的4种匹配模式小结

    正则表达式常见的4种匹配模式小结

    目录0.写在前面1.不区分大小写模式2.点号通配模式3.多行匹配模式4.注释模式5.写在最后0.写在前面 今天一起来学习下正则中的匹配模式,所谓的
    2021-08-04
  • shell脚本中的正则表达式详解

    shell脚本中的正则表达式详解

    正则表达式的概念及特点:   正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个
    2021-08-04
  • Java正则表达式里隐藏的陷阱

    Java正则表达式里隐藏的陷阱

    前几天线上一个项目监控信息突然报告异常,上到机器上后查看相关资源的使用情况,发现 CPU 利用率将近 100%。通过 Java 自带的线程 Dump 工具
    2021-08-04
  • Java正则表达式实现经纬度的合法性操作

    Java正则表达式实现经纬度的合法性操作

    Java正则表达式 经纬度合法性 经度: -180.0~+180.0(整数部分为0~180,必须输入1到5位小数) 正则表达式: /^[\-\+]?(0?\d{1,2}
    2021-08-04
  • Idea使用正则表达式批量替换字符串的方法

    Idea使用正则表达式批量替换字符串的方法

    由于一开始的粗放扩张,公司项目代码里,遗留有很多类似魔法数的写死的id,导致现在维护困难。于是交给我任务,将这些id替换成静态变量。 这
    2021-08-04
  • .net core异常中间件的使用

    .net core异常中间件的使用

    目录正文结 正文 if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } 这样写入中间件哈,那么在env环境下就会去执行UseDe
    2021-08-04
  • ASP.NET Core文件压缩常见使用误区(最佳实践)

    ASP.NET Core文件压缩常见使用误区(最佳实践)

    前言   在微软官方文档中,未明确指出文件压缩功能的使用误区。   本文将对 ASP.NET Core 文件响应压缩的常见使用误区做出说明。 误区1:
    2021-08-04
  • .Net Core中使用Autofac替换自带的DI容器的示例

    .Net Core中使用Autofac替换自带的DI容器的示例

    目录项目创建方案演示.Net Core自带DI不同的特性批量注入属性注入存储并提取容器实例为什么叫浅谈呢?就是字面上的意思,讲得比较浅,又不是
    2021-08-04

最新评论