《正则表达式经典实例(第2版)》——2.21 把部分的正则匹配添加到替代文本中

简介: 实例2.10讲解了在正则表达式中如何使用捕获分组来多次匹配相同的文本。在正则表达式中,每个捕获分组匹配到的文本在每次成功匹配之后都是可用的。你可以把部分或者所有捕获分组中的文本按照任意顺序甚至多次插入到替代文本中。

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

2.21 把部分的正则匹配添加到替代文本中

问题描述
匹配任意10个数字的连续序列,如1234567890。并把这个序列转换成(美国)电话号码的常见格式,如(123) 456-7890,

解决方案
正则表达式

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

替代文本

($1)●$2-$3
替代文本流派:.NET、Java、JavaScript、PHP、Perl
(${1})●${2}-${3}
替代文本流派:.NET、PHP、Perl
(\1)●\2-\3
替代文本流派:PHP、Python、Ruby

讨论
使用捕获分组的替代
实例2.10讲解了在正则表达式中如何使用捕获分组来多次匹配相同的文本。在正则表达式中,每个捕获分组匹配到的文本在每次成功匹配之后都是可用的。你可以把部分或者所有捕获分组中的文本按照任意顺序甚至多次插入到替代文本中。

一些流派,如Python和Ruby,在正则表达式和替代文本中对于反向引用使用相同的语法«1»。其他流派使用的则是Perl中的语法«$1»,也就是说使用的是美元符号而不是反斜杠。PHP对于两种语法都支持。

在Perl中,«$1»以及更高编号的分组实际上都是变量,它们的值会在每次正则匹配成功之后进行设置。你可以在代码中的任意地方使用它们,直到下一次正则匹配开始。.NET、Java、JavaScript和PHP只在替代文本语法中支持«$1»。这些编程语言还提供了其他在代码中访问捕获分组的方式。这会在第3章中详细解释。

$10及更多分组
本书中的所有正则流派都支持在单个正则表达式中使用最多99个捕获分组。在替代文本中,对于«$10»或«10»以及更多的分组则会产生二义性。这些可以被解释为是第10个捕获分组,或者是第一个捕获分组后跟着一个字面上的0。

.NET、XRegExp、PHP和Perl允许在数字周围使用花括号来澄清意图。«${10}» 总是代表第10个捕获分组,而«${1}0»则总是意味着第一个分组后跟着一个字面上的0。

Java和JavaScript对于«$10»使用了更加聪明的处理办法。如果在你的正则表达式中存在这个两位数的捕获分组的话,那么两位数字都会用于引用捕获分组。如果并不存在这么多捕获分组的话,那么只有第一个数字用来引用分组,这样第二个数字就当作了字面字符。因此«$23»只有在它存在的时候才被认为是第23个捕获分组。否则,它被当作是第2个捕获分组后面跟着一个字面上的«3»。

.NET、XRegExp、PHP、Perl、Python和Ruby总是把«$10»和«10»视为第10个捕获分组,而不管它们是否真的存在。如果它不存在的话,就会出现引用不存在的分组的状态。

对不存在的分组的引用
在这个实例的解决方案中的正则表达式拥有3个捕获分组。如果你在替代文本中输入了«$4»或«4»,就添加了一个对不存在的捕获分组的引用。这可能会触发如下的3种不同的行为。

Java、XRegExp和Python会报错,并且抛出异常或者返回错误消息。因此不要在这些流派中使用无效的反向引用。(事实上,你不应当在任何流派中使用无效的反向引用。)如果想要添加的是字面上的«$4»或«4»,就需要对美元符号或反斜杠进行转义。实例2.19中对此有详细的解释。

PHP、Perl和Ruby会替换在替代文本中所有的反向引用,也包括了那些指向不存在的分组的引用。不存在的分组显然不会捕获任何文本,因此对它们的引用也就简单地被替换为空。

最后,.NET和JavaScript(未使用XRegExp时)则把对不存在分组的引用当作是替代文本中的字面文本。

如果某个分组在正则表达式中存在,匹配中却没有捕获到任何东西,无论是什么流派,它仍然可以在替换文本中使用,只不过它们真实的值是空串。

使用命名捕获的解决方案
正则表达式

\b(?<area>\d{3})(?<exchange>\d{3})(?<number>\d{4})\b
正则选项:无
正则流派:.NET、Java 7、XRegExp、PCRE 7、Perl 5.10、Ruby 1.9
\b(?'area'\d{3})(?'exchange'\d{3})(?'number'\d{4})\b
正则选项:无
正则流派:.NET、PCRE 7、Perl 5.10、Ruby 1.9
\b(?P<area>\d{3})(?P<exchange>\d{3})(?P<number>\d{4})\b
正则选项:无
正则流派:PCRE、Perl 5.10、Python

替代文本

(${area})●${exchange}-${number}
替代文本流派:.NET、Java 7、XRegExp
(\g<area>)●\g<exchange>-\g<number>
替代文本流派:Python
(\k<area>)●\k<exchange>-\k<number>
替代文本流派:Ruby 1.9
(\k'area')●\k'exchange'-\k'number'
替代文本流派:Ruby 1.9
($+{area})●$+{exchange}-$+{number}
替代文本流派:Perl 5.10
($1)●$2-$3
替代文本流派:PHP

支持命名捕获的流派
如果你在正则表达式中使用了命名捕获分组,那么在.NET、Java 7、XRegExp、Python和Ruby 1.9中允许在替代文本中使用命名反向引用。在替代文本使用的命名反向引用语法与正则表达式中使用的不同。

Ruby在替代文本中使用与其在正则表达式中一样的反向引用语法。对于Ruby 1.9中的命名捕获分组,它的语法是«k»或«k'group'»。你可以选择尖括号也可以选择单引号,只看哪种方便。

Perl 5.10及以后版本将命名捕获分组匹配的文本保存在散列变量(hash)%+中。你可以使用$+{name}获得名为“name”的分组匹配的文本。Perl在替代文本中插入变量值,所以在替代文本中可以把«$+{name}»视为命名反向引用。

PHP(使用PCRE)在正则表达式中支持命名捕获分组,但是在替代文本中则不支持。你可以在替代文本中使用编号的反向引用来引用正则表达式中的命名捕获分组。PCRE会对所有命名和不命名的分组进行编号,顺序是从左向右。

.NET、Java 7、XRegExp、Python和Ruby 1.9同样允许使用编号来引用命名分组。然而,.NET对于命名分组则采用了不同的编号策略,这在实例2.11中已经进行了讲解。不推荐在.NET、Java 7、XRegExp、Python或Ruby中混合使用命名和编号。要么所有分组都命名,要么所有分组都不命名。对于命名分组,应该总是使用命名的反向引用。

相关文章
|
1月前
|
Java 程序员
Java 异常处理与正则表达式详解,实例演练及最佳实践
在 Java 代码执行期间,可能会发生各种错误,包括程序员编码错误、用户输入错误以及其他不可预料的状况。 当错误发生时,Java 通常会停止并生成错误消息,这个过程称为抛出异常。 try...catch 语句 try 语句允许您定义一段代码块,并在其中测试是否发生错误。 catch 语句允许您定义一段代码块,当 try 块中发生错误时执行该代码块。 try 和 catch 关键字成对使用,语法如下:
43 0
|
4月前
|
机器学习/深度学习 存储 JavaScript
正则表达式基础语法与Java、JS使用实例
正则表达式基础语法与Java、JS使用实例
72 1
|
7月前
|
Java
Java正则表达式校验实例
Java正则表达式校验实例
50 0
|
1月前
|
Linux Perl
使用awk和正则表达式过滤文本或字符串 - 详细指南和示例
使用awk和正则表达式过滤文本或字符串 - 详细指南和示例
65 0
|
2月前
|
开发者 Python
Python中的正则表达式:re模块详解与实例
Python中的正则表达式:re模块详解与实例
|
7月前
|
Unix Linux
如何在 Linux 中使用 Grep 和正则表达式进行文本搜索?
如何在 Linux 中使用 Grep 和正则表达式进行文本搜索?
197 5
|
8月前
|
Shell
shell中正则表达式中字符的应用具体实例以及详解
shell中正则表达式中字符的应用具体实例以及详解
94 3
|
8月前
|
算法 C语言 数据安全/隐私保护
【C++技能树】快速文本匹配 --正则表达式介绍与C++正则表达式使用
假设要判断一个QQ号是否有效,他必须满足以下三个规则
70 0
|
10月前
|
Python
34.从入门到精通:Python3 正则表达式检索和替换 repl 参数是一个函数 正则表达式对象 正则表达式修饰符 - 可选标志 正则表达式模式* 正则表达式实例
34.从入门到精通:Python3 正则表达式检索和替换 repl 参数是一个函数 正则表达式对象 正则表达式修饰符 - 可选标志 正则表达式模式* 正则表达式实例
|
11月前
|
Python
Python正则表达式匹配电话号码和邮箱实例演示,正则表达式的基本用法
Python正则表达式匹配电话号码和邮箱实例演示,正则表达式的基本用法
204 0