《正则表达式经典实例(第2版)》——2.12 把正则表达式的一部分重复多次

简介: 如果我们使用可变次数重复,并把n设置为0,事实上我们就是把在该量词之前的记号变成了可选的。‹h{0,1}›匹配一次‹h›或者根本不存在。如果不存在h,那么‹h{0,1}›会得到一个长度为0的匹配。如果你使用‹h{0,1}›来作为一个正则表达式,那么它会在目标文本中每个不是h的字符之前找到一个长度为0的匹配。

本节书摘来自异步社区《正则表达式经典实例(第2版)》一书中的第2章,第2.12节,作者: 【美】Jan Goyvaerts , Steven Levithan著,更多章节内容可以访问云栖社区“异步社区”公众号查看

2.12 把正则表达式的一部分重复多次

问题描述
创建正则表达式来匹配下列种类的数字。

  • 一个googol(一个100位的十进制整数)。
  • 一个32位的十六进制整数。
  • 一个32位的十六进制整数,带有一个可选的h后缀。
  • 一个浮点数,包含可选的整数部分、必需的小数部分和可选的指数部分。每个部分都允许任意多个数字。
    解决方案

Googol

\b\d{100}\b
正则选项:无
正则流派:.NET、Java、JavaScript、PCRE、Perl、Python、Ruby

十六进制整数

\b[a-f0-9]{1,8}\b
正则选项:不区分大小写
正则流派:.NET、Java、JavaScript、PCRE、Perl、Python、Ruby

带可选后缀的十六进制整数

\b[a-f0-9]{1,8}h?\b
正则选项:不区分大小写
正则流派:.NET、Java、JavaScript、PCRE、Perl、Python、Ruby

浮点数

\d*\.\d+(e\d+)?
正则选项:不区分大小写
正则流派:.NET、Java、JavaScript、PCRE、Perl、Python、Ruby

讨论
固定次数重复
量词‹{n}›用来重复之前的正则表达式记号n次,其中n是一个正整数。在‹bd{100}b›中的‹d{100}›会匹配一个包含100个数字的字符串。你也可以通过把‹d›敲100遍来达到同样的效果。

‹{1}›重复之前的记号一次,这样和没有任何量词是等价的。‹ab{1}c›与‹abc›是相同的正则表达式。

‹{0}›重复之前的记号0次,实际上也就是把它从正则表达式中删除。‹ab{0}c›与‹ac›是相同的正则表达式。

可变次数重复
对于可变次数重复,我们使用量词‹{n,m}›,其中n是一个正整数,并且m大于n。‹b[a-f0-9]{1,8}b›匹配一个包含1~8个数字的十六进制整数。对于可变次数重复,尝试重复的顺序就变得至关重要。这会在实例2.13中详细讲解。

如果n和m是相等的,那么我们就会得到固定次数的重复。‹bd{100,100}b›与‹bd{100}b›是相同的正则表达式。

无限次数重复
量词‹{n,}›支持无限次数重复,其中n是一个正整数。实际上,无限次数重复是一个没有上限的可变次数重复。

‹d{1,}›匹配至少一个数字,‹d+›也一样。在一个不是量词的正则表达式记号之后添加一个加号,意味着“一次或多次”。实例2.13会讲解在量词之后跟加号的含义。

‹d{0,}›匹配至少0个数字,‹d*›也一样。星号永远都意味着“0次或多次”。除了支持无限次数重复之外,‹{0,}›和星号还把之前的记号变成了可选的。

设置可选内容
如果我们使用可变次数重复,并把n设置为0,事实上我们就是把在该量词之前的记号变成了可选的。‹h{0,1}›匹配一次‹h›或者根本不存在。如果不存在h,那么‹h{0,1}›会得到一个长度为0的匹配。如果你使用‹h{0,1}›来作为一个正则表达式,那么它会在目标文本中每个不是h的字符之前找到一个长度为0的匹配。每个h则会成功匹配一个字符(也就是h)。

‹h?›与‹h(0,1)›的效果是一样的。在一个合法和完整的非量词正则表达式记号之后的问号意味着“0或1次”。下一个实例会解释在量词之后的问号的含义。

screenshot在一个起始括号之后使用问号或者任意其他量词,都是一个语法错误。Perl和沿用它的流派利用它为正则语法添加“Perl扩展”。前面的实例讲解了非捕获分组和命名捕获分组,它们都使用了在起始括号之后的问号来作为其语法的一部分。这些问号根本不是量词,它们只是属于非捕获分组和命名捕获分组的语法中的一部分。随后的实例中会讲解使用‹(?›语法的更多不同用途的分组。
重复分组
如果在分组的结束括号之后放一个量词的话,那么整个分组就会重复。‹(?:abc){3}›与‹abcabcabc›是相同的。

量词还可以进行嵌套。‹(ed+)?›匹配一个e之后跟着至少一个数字,或者是一个长度为0的匹配。在我们的浮点数的正则表达式中,这是可选的指数部分。

捕获分组也可以重复。在实例2.9中解释过,分组匹配在每次引擎退出该分组的时候捕获文本,并会覆盖该分组在之前匹配的任何文本。‹(dd){1,3}›会匹配一个包含2个、4个或6个数字的字符串。引擎会退出该分组3次。当这个正则表达式匹配到123456的时候,捕获分组中保存的是56,因为该分组的最后一次重复存储的是56。另外两次分组匹配的文本,也就是12和34,是无法获取的。

‹(dd){3}›会与‹dddd(dd)›捕获相同的文本。如果想要用捕获分组来捕获所有2个、4个或6个字符,而不只是最后2个,就必须用捕获分组包围量词,而不只是重复该捕获分组:‹((?:dd){1,3})›。这里我们用非捕获分组取代了捕获分组的分组功能。我们也可以使用两个捕获分组:‹((dd){1,3})›。在后一个正则表达式匹配123456的时候,‹1›中保存的是123456,而在‹2›中则保存了56。

只有.NET的正则表达式引擎才支持获取捕获分组的所有重复捕获的文本。如果直接查找该分组的Value属性,你会得到字符串56,就像所有其他正则表达式引擎一样。在正则表达式中的反向引用和替代文本也会代入56,但是如果使用分组的CaptureCollection,你就会得到一个栈,其中包含56、34和12。

相关文章
|
7月前
|
Java 程序员
Java 异常处理与正则表达式详解,实例演练及最佳实践
在 Java 代码执行期间,可能会发生各种错误,包括程序员编码错误、用户输入错误以及其他不可预料的状况。 当错误发生时,Java 通常会停止并生成错误消息,这个过程称为抛出异常。 try...catch 语句 try 语句允许您定义一段代码块,并在其中测试是否发生错误。 catch 语句允许您定义一段代码块,当 try 块中发生错误时执行该代码块。 try 和 catch 关键字成对使用,语法如下:
109 0
|
7月前
|
机器学习/深度学习 存储 JavaScript
正则表达式基础语法与Java、JS使用实例
正则表达式基础语法与Java、JS使用实例
109 1
|
Java
Java正则表达式校验实例
Java正则表达式校验实例
84 0
|
5月前
|
Java
正则表达式在Java中的应用与实例
正则表达式在Java中的应用与实例
|
7月前
|
开发者 Python
Python中的正则表达式:re模块详解与实例
Python中的正则表达式:re模块详解与实例
272 0
|
Shell
shell中正则表达式中字符的应用具体实例以及详解
shell中正则表达式中字符的应用具体实例以及详解
141 3
34.从入门到精通:Python3 正则表达式检索和替换 repl 参数是一个函数 正则表达式对象 正则表达式修饰符 - 可选标志 正则表达式模式* 正则表达式实例
34.从入门到精通:Python3 正则表达式检索和替换 repl 参数是一个函数 正则表达式对象 正则表达式修饰符 - 可选标志 正则表达式模式* 正则表达式实例
|
Python
Python正则表达式匹配电话号码和邮箱实例演示,正则表达式的基本用法
Python正则表达式匹配电话号码和邮箱实例演示,正则表达式的基本用法
267 0
|
JavaScript 前端开发
JavaScript使用正则表达式进行邮箱表单验证实例
JavaScript使用正则表达式进行邮箱表单验证实例
96 0
|
C语言
【正则表达式】快速学习一个c语言的实例
【正则表达式】快速学习一个c语言的实例
154 0