《正则表达式经典实例(第2版)》——2.8 匹配多个选择分支之一

简介: 本书中的所有正则表达式流派都会使用正则制导的引擎。正则表达式依赖于这台引擎来工作。这里所说的正则制导1FF的含义是,在目标文本中的每个字符位置会首先匹配该正则表达式的所有可能排列,然后才会到下一个字符位置进行匹配尝试。

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

2.8 匹配多个选择分支之一

问题描述
创建一个正则表达式,当把它重复应用到目标文本Mary, Jane, and Sue went to Mary's house之上时,会匹配到Mary、Jane、Sue,且能再次匹配到Mary。之后再进行的匹配尝试都会失败。

解决方案

Mary|Jane|Sue
正则选项:无
正则流派:.NET、Java、JavaScript、PCRE、Perl、Python、Ruby

讨论
竖线(vertical bar),或称作管道符号(pipe symbol),会把正则表达式拆分成多个选择分支。‹Mary|Jane|Sue›会在每次匹配尝试时匹配Mary,或者Jane,或者Sue。每次只会匹配一个名字,但是每次却可以匹配不同的名字。

本书中的所有正则表达式流派都会使用正则制导的引擎。正则表达式依赖于这台引擎来工作。这里所说的正则制导1FF的含义是,在目标文本中的每个字符位置会首先匹配该正则表达式的所有可能排列,然后才会到下一个字符位置进行匹配尝试。

当你把‹Mary|Jane|Sue›应用到Mary, Jane, and Sue went to Mary's house的时候,在字符串起始处立即就会找到匹配Mary。

当你把同一个正则表达式应用到余下的字符串的时候,比如说,你可以在文本编辑器中单击“查找下一个”,正则引擎就会尝试在该字符串中的第一个逗号处匹配‹Mary›。匹配会失败。然后,它会在同一个位置尝试去匹配‹Jane›,这也会失败。接着在逗号处匹配‹Sue›,当然也会失败。只有在所有匹配都失败之后,正则引擎才会前进到字符串中的下一个字符。从第一个空格开始匹配,3个选择分支都会得到同样的失败结果。

从字母J开始匹配的时候,第一个选择分支‹Mary›会出现匹配失败。接着第二个选择分支,也就是‹Jane›,会在字母J处匹配成功。它匹配的是Jane。正则引擎宣布匹配成功。

需要注意的是:虽然在目标文本中还存在另外一个Mary,而且在正则表达式中‹Mary›出现在‹Jane›之前,但是这里匹配到的依然是Jane。至少在这个例子中,正则表达式中各分支的顺序并不重要。正则表达式会查找最左边的匹配。它会从左向右扫描目标文本,在扫描的每一步中都会尝试正则表达式中的所有选择分支,而当其中任意一个选择分支产生一个合法匹配的时候,匹配过程就会停在这个位置。

如果我们再次对字符串余下部分进行查找,那么会找到Sue。而第四次查找则会再一次找到Mary。如果你告诉正则引擎进行第五次查找,就会失败,因为这三个选择分支都无法匹配余下的’s house字符串。

只有当在字符串中的同一个位置存在两个选择分支同时匹配的时候,正则式中的选择分支的顺序才有意义。例如,正则式‹Jane|Janet›在匹配目标文本Her name is Janet的时候,就会有两个选择分支在同一位置出现匹配。在此正则表达式中并不存在单词边界。事实上,‹Jane›是否只匹配到Her name is Janet中的单词Janet的一部分并不重要。

‹Jane|Janet›之所以会匹配到Her name is Janet中的Jane,是因为一个正则制导的正则表达式引擎是遵循“浅尝辄止”的工作原则的(eager)。除了会从左向右扫描目标文本,查找最左匹配之外,它还会从左向右扫描正则式中的选择分支。而一旦它找到一个匹配的选择分支,正则引擎就会立即停止。

当‹Jane|Janet›到达了Her name is Janet中的J的时候,第一个选择分支‹Jane›,成功匹配。第二个选择分支则根本没有进行尝试。如果我们告诉引擎接着查找下一个匹配的话,这时候在目标文本中剩下的只有t。此时两个选择分支都不能成功匹配。

要想不让Jane抢夺Janet的光环,有两种方式。第一种方式是把较长的选择分支放在前面:‹Janet|Jane›。另外一种更为可靠的方式是清晰地表达我们所期望的结果:我们在查找名字,而名字应该是完整的单词。正则表达式并不会处理单词,但是它们可以处理单词边界。

因此,‹bJaneb|bJanetb›和‹bJanetb|bJaneb›都会匹配到Her name is Janet中的Janet。由于单词边界的原因,只有一个选择分支会成功匹配。在这里我们看到选择分支的顺序依然无关紧要。

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