[b]正则中的子表达式[/b]
<b>实例一. </b>
<b>重要提醒</b>
1. 子表达式是一个更大的表达式的一部分;把一个表达式划分为一系列肚子表达式的目的是
为了把那些子表达式当做一个独立元素来使用(类似于独立字符)
2. 子表达式必须用(和)括起来。(和)是元字符。
3. 复杂而高效正则会多次用子表达式休息。
正则表达式复杂而高效的模式会用到子表达式(对表达式进行分组和归类)。
前面我们提到过如何匹配一个字符的连续多次重复。如:\d+ 匹配一个或多个数字字符;
https?:// 将匹配http:// 和https://
<b>实例一. </b>
有这么一个场景: 找出文本中连续两次货更多次的重复出现找出来。 文本如下: I am the author of books Windows and other subjects.
匹配表达式采用重复匹配{2,}, 如是 {2,}
结果匹配不出来。因为用来表明重复次数的元字符?或*或{2,} 等只作用于紧挨着她得前一个字符或元字符。
如果要完成上面提到的任务需要用到子表达式,其模式写法为( ){2,}
( )是一个子表达式; 在此它被视为一个独立的元素/"字符",紧跟后面的{2,}将作用于这个子表达式。
B.前面的例子中提到,正则匹配查找文本中的IP地址:
用到的正则是\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}
分析发现: B.1 \d{1,3}在这个模式里重复了4次,它们分别匹配IP地址里的一组数字。(IP地址里的4组数字由.分隔,该字符又模式里的转义序列\.负责匹配)
B.2 仔细一看,可以发现\d{1,3}\.联系出现了3次,它同样可以被表达为一个重复。
鉴于上面的分析,使用子表达式会更简洁省事。 (\d{1,3}\.){3}\d{1,3}
实例二如下:
Major: Physics
Birth: 1985-05-30
Place: China
把上面记录的文本中年份数字完整地找出来。
一般可能写法是: 19|20\d{2} | 字符是正则表达式语言里的或操作符, 19|20讲匹配数字序列19或20
上面的正则表达式初一看感觉是没有任何问题的,但是匹配的结果确不是我们想要的。因为它只匹配到了19.
原因分析: | 操作符是把位于它左边和右边的两个部分都作为一个整体来看待的,它会把模式19|20\d{2} 解释为19或20\d{2}即将\d{2}解释为以20开头的那个表达式的一部分。
换句话说19|20\d{2}将匹配数字19或以20开头的任意4为数字。
解决办法是: 把19|20 归为一个子表达式如: (19|20)\d{2} 把所有的选项都归纳到了一个子表达式里,这将向|表明用户打算匹配的是表达式里的选项之一。
子表达式的嵌套
子表达式是容许多重嵌套,但是实际工作中还是应该适可而止。
多重嵌套的子表达式可以构造出功能非常强大的正则表达式来,但这难免会让模式变得难以阅读和理解,而这真是很多人觉得正则表达式难以学习和掌握的原因之一。
其实是表面现象掩盖了一个事实:绝大多数嵌套子表达式都没有他们看上去那么复杂。
看一个前面提到的匹配IP的模式:(\d{1,3}\.){3}\d{1,3} ,初看没有问题能匹配到IP但是他忽略了一点此模式还能匹配出非法的IP如400.23.35.253等等。
高效而正确的写法可以是:(\d{1,2})|(1\d{1,2})|(2[0-4]\d)|(25[0-5])
合法的IP应该符合的规则是:
任何一个一位或者两位的数字;任何一个以1开头的3位数字;任何以2开头,第二位数字在0-4之间的3位数;任何以25开头,第三位在0-5之间的3位数字。
<b>重要提醒</b>
在这里一个重要提醒:
把必须匹配的情况考虑周全并写出一个匹配结果符合预期的正则表达式很容易,但
是把不需要匹配的情况也考虑周全并确保他们都将被排除在匹配结果意外往往要难很多。
正则表达式是一个十分考察个人逻辑思维能力。
在构造定义一个正则表达式的时候,一定要把你想匹配什么和你不想匹配什么详细地定义清楚。
子表达式的作用是把同一个表达式的各个相关的分组做好在一起。 在表达式必须用(和)来定义。
子表达式常见用途:对重复次数元字符的作用对象做出的设定和控制、对|操作符的OR添加