正则表达式 - 量词

news2024/11/28 21:41:21

目录

一、贪心、懒惰和占有

二、用 *、+ 和 ? 进行匹配

三、匹配特定次数

四、懒惰量词

五、占有量词

六、示例——括号字符串计数


        {m,n} 是通用形式的量词,正则表达式还有三个常用量词,分别是 +、?、*。它们的形态虽然不同于 {m,n},功能却是相同的,因此也可以把它们理解为“量词简记法”。具体说明见下表。

常用量词

{m,n}等价形式

说明

*

{0,}

出现零次、一次或多次

+

{1,}

出现至少一次

?

{0,1}

出现至多一次

一、贪心、懒惰和占有

        量词自身是贪心的。贪心量词会首先匹配整个字符串。尝试匹配时,它会选定尽可能多的内容,也就是整个输入。量词首次尝试匹配整个字符串,如果失败则回退一个字符后再次尝试。这个过程叫做回溯(backtracking)。它会每次回退一个字符,直到找到匹配的内容或者没有字符可尝试为止。此外,它还记录所有的行为,因此相较另两种方式它对资源的消耗最大。

        懒惰(有时也说勉强)量词则使用另一种策略。它从目标的起始位置开始尝试寻找匹配,每次检查字符串的一个字符,寻找它要匹配的内容。最后,它会尝试匹配整个字符串。要使一个量词成为懒惰的,必须在普通量词后添加一个问号 ?。

        占有量词会覆盖整个目标然后尝试寻找匹配内容,但它只尝试一次,不会回溯。占有量词就是在普通量词之后添加一个加号 +。

二、用 *、+ 和 ? 进行匹配

        这些量词默认是贪心的,这意味它们在第一次尝试时会尽可能多地匹配字符。

drop table if exists t1;
create table t1 (a varchar(10));
insert into t1 values
('1'),('22'),('333'),('4444'),('55555'),('666666'),
('7777777'),('88888888'),('999999999'),('0000000000');

        .* 匹配任何字符零次或多次,因此会以贪心的方式匹配所有行。

mysql> select regexp_substr(a,'.*') from t1;
+-----------------------+
| regexp_substr(a,'.*') |
+-----------------------+
| 1                     |
| 22                    |
| 333                   |
| 4444                  |
| 55555                 |
| 666666                |
| 7777777               |
| 88888888              |
| 999999999             |
| 0000000000            |
+-----------------------+
10 rows in set (0.01 sec)

        9* 匹配 0个到多个9,因此会以贪心的方式匹配所有行。数字9的行完全匹配,其它行匹配空串。

mysql> select distinct regexp_substr(a,'9*') from t1;
+-----------------------+
| regexp_substr(a,'9*') |
+-----------------------+
|                       |
| 999999999             |
+-----------------------+
2 rows in set (0.01 sec)

        9.* 匹配 9 后面跟着任何字符零次或多次,因此包含数字9的行,其它行不匹配,因此返回NULL,注意不是空串!

mysql> select distinct regexp_substr(a,'9.*') from t1;
+------------------------+
| regexp_substr(a,'9.*') |
+------------------------+
| NULL                   |
| 999999999              |
+------------------------+
2 rows in set (0.00 sec)

        9+ 匹配 1个到多个9,结果包含数字9的行。

mysql> select distinct regexp_substr(a,'9+') from t1;
+-----------------------+
| regexp_substr(a,'9+') |
+-----------------------+
| NULL                  |
| 999999999             |
+-----------------------+
2 rows in set (0.00 sec)

        9? 匹配 0个或1个9。数字9的行只匹配第一个字符9,其它行匹配空串。

mysql> select distinct regexp_substr(a,'9?') from t1;
+-----------------------+
| regexp_substr(a,'9?') |
+-----------------------+
|                       |
| 9                     |
+-----------------------+
2 rows in set (0.00 sec)

        99? 匹配 9后面跟0个或1个9。数字9的行匹配前两个字符9,其它行不匹配。

mysql> select distinct regexp_substr(a,'99?') from t1;
+------------------------+
| regexp_substr(a,'99?') |
+------------------------+
| NULL                   |
| 99                     |
+------------------------+
2 rows in set (0.00 sec)

三、匹配特定次数

        使用花括号可以限制某个模式在某个范围内匹配的次数,未经修饰的量词就是贪心量词。例如 7{1} 会匹配第一次出现的7。

mysql> select regexp_substr(a,'7{1}') from t1 where a regexp '7{1}';
+-------------------------+
| regexp_substr(a,'7{1}') |
+-------------------------+
| 7                       |
+-------------------------+
1 row in set (0.01 sec)

        要匹配一个或多个数字7,只要加一个逗号即可。

mysql> select regexp_substr(a,'7{1,}') from t1 where a regexp '7{1,}';
+--------------------------+
| regexp_substr(a,'7{1,}') |
+--------------------------+
| 7777777                  |
+--------------------------+
1 row in set (0.00 sec)

        7+ 和 7{1,} 本质上是一样的;7* 和 7{0,}、7? 和 7{0,1} 也是一样的。还可以匹配 m到n 次,比如 7{3,5} 会匹配三个、四个以及五个7。

mysql> select regexp_substr(a,'7{3,5}') from t1 where a regexp '7{3,5}';
+---------------------------+
| regexp_substr(a,'7{3,5}') |
+---------------------------+
| 77777                     |
+---------------------------+
1 row in set (0.00 sec)

        可以看出,花括号(或者说范围语法)是最灵活和精确的量词。

四、懒惰量词

        理解懒惰特性最好的方式就是看看实际应用,尝试用问号 ? 匹配零个或者一个5。

mysql> select distinct regexp_substr(a,'5?') from t1 where a regexp '5?';
+-----------------------+
| regexp_substr(a,'5?') |
+-----------------------+
|                       |
| 5                     |
+-----------------------+
2 rows in set (0.01 sec)

        请再加一个 ? 来使量词变为懒惰的。

mysql> select distinct regexp_substr(a,'5??') from t1 where a regexp '5??';
+------------------------+
| regexp_substr(a,'5??') |
+------------------------+
|                        |
+------------------------+
1 row in set (0.00 sec)

        现在它看起来只匹配空串,其原因是该模式已经是懒惰的了。也就是说,它不会强制匹配第一个5。懒惰的基本特性就是匹配尽可能少的字符。试一下匹配零次或多次的量词。

mysql> select distinct regexp_substr(a,'5*?') from t1 where a regexp '5*?';
+------------------------+
| regexp_substr(a,'5*?') |
+------------------------+
|                        |
+------------------------+
1 row in set (0.01 sec)

        它也只匹配空串,因为它可以选择匹配最少的次数——零次。再试一下匹配一次或多次。

mysql> select distinct regexp_substr(a,'5+?') from t1 where a regexp '5+?';
+------------------------+
| regexp_substr(a,'5+?') |
+------------------------+
| 5                      |
+------------------------+
1 row in set (0.00 sec)

        懒惰特性使其只匹配了一个5。它只需要做到这个程度就可以了。使用 m和n 方式匹配时就更为有趣了。

mysql> select distinct regexp_substr(a,'5{2,5}?') from t1 where a regexp '5{2,5}?';
+----------------------------+
| regexp_substr(a,'5{2,5}?') |
+----------------------------+
| 55                         |
+----------------------------+
1 row in set (0.00 sec)

        只匹配了两个5,而不像贪心量词那样匹配五个。

        下表列出了懒惰量词。什么时候懒惰式匹配最实用?如果想匹配最少而不是最多数目的字符,就可以使用懒惰量词。

语法

说明

??

懒惰匹配零次或一次

+?

懒惰匹配一次或多次

*?

懒惰匹配零次或多次

{n}?

懒惰匹配n次

{n,}?

懒惰匹配n次或多次

{m,n}?

懒惰匹配m至n次

五、占有量词

        占有式匹配很像贪心式匹配,它会选定尽可能多的内容。但与贪心式匹配不同的是它不进行回溯。它不会放弃所找到的内容,这也是把它称为占有式(possessive)的原因。占有量词的优点是速度快,因为无需回溯。当然,匹配失败的话也很快。

        为了理解这一点,我们先尝试匹配以零开头的多个零。

mysql> select distinct regexp_substr(a,'0.*+') from t1 where a regexp '0.*+';
+-------------------------+
| regexp_substr(a,'0.*+') |
+-------------------------+
| 0000000000              |
+-------------------------+
1 row in set (0.00 sec)

        匹配了所有的零。占有式的匹配看起来和贪心式的匹配是一样的,但没有回溯。可以证明一下,输入带有结尾零的表达式。

mysql> select distinct regexp_substr(a,'.*+0') from t1 where a regexp '.*+0';
Empty set (0.01 sec)

        没有匹配——原因就是没有回溯。它一下就选定了所有的输入,不再回过来查看。它一下子没在结尾找到零,也不知道该从哪里找起。如果将加号去掉,它会找到所有的0,因为它变回贪心式匹配了。

mysql> select distinct regexp_substr(a,'.*0') from t1 where a regexp '.*0';
+------------------------+
| regexp_substr(a,'.*0') |
+------------------------+
| 0000000000             |
+------------------------+
1 row in set (0.00 sec)

        当知道文本中的内容就知道在哪里可以找到匹配时,应该会使用占有量词。它不在乎是否会选定所有内容。占有式匹配有助于提高匹配的性能。下表列出了占有量词。

语法

说明

?+

占有匹配零次或一次

++

占有匹配一次或多次

*+

占有匹配零次或多次

{n}+

占有匹配n次

{n,}+

占有匹配n次或多次

{m,n}+

占有匹配m至n次

六、示例——括号字符串计数

        有一张表 t1 存储用户评论内容,如下所示(只列出相关列):

        现在想得出每种评论字数的个数,每个字符包括标点、空格、表情符号都算一个字,但每对中括号连同其中的内容只算一个字。对于上面的数据行,结果为:

        第一感觉这是使用正则表达式的场景。只要将每对中括号连同其中的内容替换为单个字符,再用char_length函数求长度即可。查询语句如下:

select char_length(regexp_replace(Content,'\\[.*?\\]', 'A')) r,count(*) 
  from t1 group by char_length(regexp_replace(Content,'\\[.*?\\]', 'A')) 
 order by r;

        \\[ 和 \\] 用于将中括号转义为普通字符。非 dotall 模式下的正则表达式中,“.”表示匹配除换行符 \n 之外的任何单字符,“*”表示零次或多次。所以 “.*” 连在一起就表示任意字符出现零次或多次。没有“?”表示贪婪模式。比如 a.*b,它将会匹配最长的以 a 开始,以 b 结束的字符串。如果用它来搜索 aabab 的话,它会匹配整个字符串 aabab。又比如模式src=`.*`, 它将会匹配以 src=` 开始,以`结束的最长的字符串。用它来搜索 <img src=``test.jpg` width=`60px` height=`80px`/> 时,将会返回 src=``test.jpg` width=`60px` height=`80px`。

        “?”跟在“*”后边用时,表示懒惰模式,就是匹配尽可能少的字符。这就意味着匹配任意数量的重复,但是在能使整个匹配成功的前提下使用最少的重复。a.*?b 匹配最短的以 a 开始,以 b 结束的字符串。如果把它应用于 aabab 的话,它会匹配 aab(第一到第三个字符)和 ab(第四到第五个字符)。又比如模式 src=`.*?`,它将会匹配 src=` 开始,以 ` 结束的尽可能短的字符串,且开始和结束中间可以没有字符,因为 * 表示零到多个。用它来搜索 <img src=``test.jpg` width=`60px` height=`80px`/> 时,将会返回 src=``。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

8年测试总结,项目/团队如何做自动化测试?效率价值?吐血整理...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 Python自动化测试&…

Linux:centos:用户基础设置》》添加,修改属性,删除,修改密码

useradd &#xff08;属性&#xff09; 用户 新建用户 usermod &#xff08;属性&#xff09; 用户 调整用户属性 userdel &#xff08;属性&#xff09; 用户 删除用户 passwd &#xff08;属性&#xff09; 用户 修改用户密…

科技云报道:国内AI大模型鏖战,上演科技罗生门

科技云报道原创。 ChatGPT的狂热从年初持续至今&#xff0c;这份狂热不仅仅来源于用户层&#xff0c;从业者、投资人以及企业可以说有过之无不及。 于是&#xff0c;这些投资人、从业者以及企业将狂热转化&#xff0c;宣布入局大模型赛道并推出相关产品。一时间&#xff0c;大…

百万年薪架构师甩出的SpringBoot趣味实战手册,GitHub标星81.6K

前言 本书内容很全面&#xff0c;囊括了Spring生态的常用技术&#xff0c;如MVC、持久化、 Redis、定时任务、消息队列、搜索引擎。本书知识讲解由浅到深&#xff0c;循序渐进&#xff0c;从Hello World讲到Spring核心原理&#xff1b;技术讲解深入浅出&#xff0c;总能以“接…

无线传感网络的节点部署覆盖及能源消耗问题研究(Matlab代码实现)

目录 &#x1f4a5;1 概述 &#x1f4da;2 运行结果 &#x1f389;3 参考文献 &#x1f468;‍&#x1f4bb;4 Matlab代码 &#x1f4a5;1 概述 随着微电子技术的不断发展,被称作传感器节点的微小智能嵌入式设备不断的被开发出来,推动了无线传感器网络的发展。一个典型的无…

Matlab Python 如何在figure上画出表格【优化】

之前写过一次博客 Matlab&Python 如何在figure上画出表格 这次是对该博客的优化 图的结果见下相对之前有很大的进步&#xff1a; coding 在这里包含数据的绘制&#xff0c;表格的添加&#xff0c;设置表格的大小、位置等 clc clear close all; path(path,E:\new_matlab_Too…

如何获取不同分区模板的基因表达矩阵,abagen: Allen 大脑图谱遗传数据工具箱的使用笔记

abagen: Allen 大脑图谱遗传数据工具箱的使用笔记 介绍使用abagen工具箱进行标准化处理和报告代码实例——获取Schaefer2018_400Parcels_7Networks的基因表达数据基于surf空间的模板基于volume空间的模板参考文献介绍 基因表达从根本上塑造了人类大脑的结构和功能结构。像Allen…

【Linux】shell编程—数组

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 一、shell数组1,数组的概念2.数组的定义 二、Shell数组操作1. 获取数组的所有元素的列表2. 获取数组的所有元素下标3.取数组的元素个数4. 获取数组的某个元素的值5.…

Jmeter 压测 QPS

文章目录 1、准备工作1.1 Jmeter的基本概念1.2 Jmeter的作用1.3.Windows下Jmeter下载安装1.4 Jmeter的目录结构1.5 启动1.6 设置中文1.6.1 设置调整1.6.2 配置文件调整&#xff08;一劳永逸&#xff09; 2、Jmeter线程组基本操作2.1 线程组是什么2.2 线程组2.2.1 创建线程组2.2…

原型part学习NeurIPS2019

当我们面临具有挑战性的图像分类任务时&#xff0c;我们希望通过分解part来解释推理。每一类别的更多原型证据有助于做出最终分类决策。作者提出一种深度网络架构&#xff1a;Prototypical Part网络即ProtoPNet。网络通过寻找原型part来解释图像&#xff0c;并基于原型part进行…

同步 Swagger URL问题, 用这个插件就可解决

这个开源的 API 管理工具叫 Postcat, 支持从 Swagger URL 增量同步 API 数据到 Postcat。 使用 进入 API 模块&#xff0c;鼠标移动到主按钮加号&#xff0c;下拉看到从 Swagger 同步 URL 的选项。 填写完配置点击立即同步即可同步 API 数据。 同步规则 新的数据覆盖旧的数据…

PHP语言调用api接口,电商平台商品详情接口(封装可高并发)

PHP是为Web而生的语言&#xff0c;它提供了一些强大的内置函数来处理HTTP请求和响应。PHP为开发人员提供了一些Web开发工具&#xff0c;包括HTML、CSS、JavaScript以及各种数据库的连接和互动。与其他Web开发工具相比&#xff0c;PHP可以更加高效地运转与发挥作用。 PHP表现出…

Matlab 非线性迭代法(3)阻尼牛顿法 L-M

高斯牛顿法详解_我只是一只自动小青蛙的博客-CSDN博客 一、思想 先看一下牛顿高斯迭代法的缺点&#xff1a; 1、在计算的过程中可能会出现奇异矩阵&#xff08;不满秩&#xff09;&#xff0c;比如&#xff1a;J(k)​)TJ(k) 为病态矩阵的时候就不能得到正确的解&#xff0c;或…

如何提升性能测试效能

上周六应邀在天津devops峰会的质量内建专场做了一次分享&#xff0c;主题是《稳定性保障利器&#xff1a;全链路压测》。 其中关于全链路压测对质量内建的意义&#xff0c;我做了一个总结&#xff0c;如下图所示。本文基于下图做了展开描述&#xff0c;仅供参考。 如何理解性能…

从零开始Vue3+Element Plus后台管理系统(八)——模仿禅道做一个Vue3版本的高级查询组件

暗黑模式 使用 Vue3element Plus 简单模仿了禅道系统的高级搜索组件&#xff0c;说简单也有点复杂&#xff0c;还没有完全开发完&#xff0c;但是大体架子有了&#xff0c;剩下一些功能点继续coding。边开发边记录吧&#xff0c;因为这个相比之前的内容确实复杂一些&#xff0c…

Java的基操,基操(一)

&#x1f525;二进制&#x1f525;二进制和十进制的转化&#x1f525;注释&#x1f525;标识符&#x1f525;关键字/保留字&#x1f525;变量(variable) &#x1f525;二进制 二进制&#xff0c;是计算技术中广泛采用的一种数制&#xff0c;由德国数理哲学大师莱布尼茨于 1679 …

Helm chart 常用命令以及原理和生产实践

问: 到哪里去搜索helm package? 答: artifacthub.io Helm 的实质就是搞一些模版&#xff0c;最终依据这些模版生成k8s的系列yaml文件(deployemnt,service,secret,map等等),从而在k8s上能够简单部署出完整应用。可以用helm template查看最终生成的k8s部署文件。 helm version…

MQTT客户端应用编程及接口分析

MQTT客户端应用编程及接口分析 MQTT协议简介 MQTT是一个基于客户端-服务器的消息发布/订阅传输协议。MQTT协议是轻量、简单、开放和易于实现的&#xff0c;这些特点使它适用范围非常广泛。 客户端服务端安装 1.安装 sudo apt-add-repository ppa:mosquitto-dev/mosquitto-…

SpringCloud_服务注册中心_Consul(八)

SpringCloud_服务注册中心_Consul(八) 分为五部分 Consul简介 安装并运行Consul 服务提供者 服务消费者 三个注册中心异同点 Consul简介 官网&#xff1a;https://developer.hashicorp.com/consul/docs/intro 是Go语言写的 Consul是一套开源的分布式服务发现和配置管理系统&am…

GB50312-2016标准中需要检测的参数(AEMFLUKE)含双绞线和光

很多同学经常搞不清GB50312-2016标准的规定测试参数&#xff0c;或者说和测试设备对不上号。特意从标准中摘抄出来&#xff0c;供大家参考。 ACR-F(Attenuation to Crosstalk Ratio at the Far-end) 衰减远端串音比 ACR-N(Attenuation to Crosstalk Ratio at the Near-end)衰…