收藏 分享(赏)

正则表达式(五):浅谈两种匹配操作.docx

上传人:wspkg9802 文档编号:4563436 上传时间:2019-01-02 格式:DOCX 页数:8 大小:45.63KB
下载 相关 举报
正则表达式(五):浅谈两种匹配操作.docx_第1页
第1页 / 共8页
正则表达式(五):浅谈两种匹配操作.docx_第2页
第2页 / 共8页
正则表达式(五):浅谈两种匹配操作.docx_第3页
第3页 / 共8页
正则表达式(五):浅谈两种匹配操作.docx_第4页
第4页 / 共8页
正则表达式(五):浅谈两种匹配操作.docx_第5页
第5页 / 共8页
点击查看更多>>
资源描述

1、正则表达式(五):浅谈两种匹配操作在正则表达式中,匹配是最最基本的操作。使用正则表达式,换种说法就是“用正则表达式去匹配文本”。但这只是广义的“匹配”,细说起来,广义的“匹配”又可以分为两类:提取和验证。所以,本篇文章就来专门讲讲提取和验证。提取提取可以理解为“用正则表达式遍历整个字符串,找出能够匹配的文本”,它主要用来提取需要的数据,常见的任务有:找出文本中的电子邮件地址,找出HTML代码中的图片地址、超链接地址提取数据时,首先要注意的,就是准确性。准确准确性分为两方面:完整和精确。前者是要提取出需要的所有文本,不能漏过;后者是要保证提取的结果中没有不需要的文本,不可出错。为保证完整,我们需

2、要考虑足够多的变体,覆盖所有情况。一般来说,要提取的数据都只有概念的描述(比如,提取一个电子邮件地址,提取一个身份证号),如果没有拿到完整规范的特征描述,可能只能凭经验总结出几条特征,然后逐步完善,也就是不断考虑新的情况,照顾到各种情况。拿“提取文本中的浮点数字符串”为例。最容易想到的情况,就是3.14、3999.2、0.36之类,也就是“数字字符串 + 小数点 + 数字字符串”,所以用表达式d+.d+,按照我们上一篇文章说过的“与或非”,三个部分都是必须出现的,所以这个表达式似乎是没问题了。d+.d+但是有些时候,0.7是写作.7 的,上面的表达式无法照顾这种情况,所以必须修改表达式:整数部

3、分是可能出现也可能不出现的,所以小数点之前的d+应该改为d*,就成了d*.d+。d*.d+但是且慢,浮点数还包括负数,比如-0.7,但现在这个表达式无法匹配最开始的符号,所以还应该改成-?d*.d+。-?d*.d+但仅仅保证完整性还不够,提取的另一方面是精确,就是排除掉那些“能够由正则表达式匹配,但其实并非期望”的字符串,所以我们还需要仔细观察目前的正则表达式,适当添加限制条件。仍然用上面的正则表达式作例子,-?d*.d+中,-?和d* 都是可能出现的元素,所以它们可能都不出现,这时候表达式能匹配.7之类,没有错;如果只出现了d*能匹配的文本,可以匹配3.14之类,也没有错;但是,如果只出现-

4、? 呢?-.7,通常来说,负的浮点数是应该写作-0.7的,而-.7显然是不合法的。所以,这个表达式应该修改为 (-?d+|d*).d+。(-?d+|d*).d+事情到这里就完整了吗?似乎还不是。我们知道有些地方,日期字符串是“2010.12.22”的形式,如果你要处理的文本中不包含这种日期字符串还好,否则,上面的表达式会错误匹配2010.12.22 或者2010.12.22 。为了避免这种情况,我们需要给表达式加上更多的限制。最直接想法就是,限定表达式两端不能出现点号.,变成(?!“; $matched = preg_match($regex, $string, $oneMatch, PREG

5、_OFFSET_CAPTURE, $lastOffset); 第3种办法是使用迭代器,Python的re.finditer()会得到一个迭代器,每次调用next(),就会获得下一次匹配的结果。这种办法目前只有Python 提供,其它语言尚不具备。代码(以Python 为例)for match in re.finditer(“d+“, “123 45 6“) print match.group(0)验证另一类“匹配”是数据验证,也就是“检查字符串能否完全由正则表达式匹配”,它主要用来测试和保证数据的合法性。比如有些网站要求你设定密码,密码只能由数字或小写字母构成,长度在6到12 个字符之间,如果

6、输入的密码不符合条件,则会提示你修改,这个任务,一般使用JavaScript的正则表达式来完成。初看起来,这也是用正则表达式在字符串中查找匹配文本。但仔细想想,两者又不一样:一般来说,提取时正则表达式匹配的开始/ 结束位置都是不确定的,需要逐次试错,才能决定;验证时,同样需要考虑准确性,但效率并不是重点考虑的因素(一把验证的文本是用户名、手机号、密码之类,不会太长),虽然也要求准确性,但匹配的开始/ 结束位置都是确定的,只要从文本的开头验证即可,不用反复推进-尝试;而且只要发现任何一个“硬性”条件无法满足(比如长度、锚点),即可失败退出。正因为验证操作有这些特点,有些语言中提供了专门的方法进行

7、正则表达式验证。如果没有,我们也可以使用简单的查找功能,只是在正则表达式的首尾加上匹配字符串起始/ 结束位置的锚点来定位,这样既保证表达式匹配的是整个字符串,也可以在无法匹配时尽早判断失败退出。常见语言中的验证方法语言 验证方法 备注Java String.matches(regex)专用于验证,返回boolean值,不需要和$PHP preg_match(regex, string) != 0preg_match返回匹配成功的次数,需要 和$.NET Regex.IsMatch(string, regex)专用于验证,返回boolean值,不需要和$Python re.search(rege

8、x, string) != None成功则返回True,否则返回False ,需要和$re.match(regex, string) != None成功则返回True,否则返回False ,需要$Ruby Regexp.match(text) != nilRegexp.match(text)返回匹配成功的起始位置,若无法匹配则返回nil ,需要和$JavaScriptRegexp.test(string)专用于验证,返回boolean值,需要和$前面说过,在验证时,文本的开始/结束位置是预先知道的,所以验证的表达式编写起来更加简单。比如之前匹配浮点数的表达式,我们首先得到的是(-?d+|d*)

9、.d+,在进行数据提取时,需要在两端加上环视,防止错误匹配其它字符;但是如果是验证浮点数,就不需要考虑两端的环视,应该/不应该出现什么字符,直接在首尾加上和 $即可,所以验证用的表达式是 (-?d+|d*).d+$。我们甚至可以简单将各个条件叠加起来,直接得到最后的表达式,比如下面这个例子:需要验证密码字符串,前期的分析总结出5条明确的规则:下面依次列出对应5条规则的表达式:如果用来提取数据,就必须把这5条规则糅合到一起。前3 条规则比较好办,可以合并为(?!-)0-9A-Za-z-6,12(?!-)$,但它与第4和第5个条件合并都不简单。与第4条规则合并的难点在于,我们无法确定这个0-9出现

10、的位置,如果简单改为 (?!-)0-9A-Za-z-6,120-90-9A-Za-z-6,12(?!-)$,看似正确,却无法保证整个字符串的长度在6-12 之间目前这个表达式的长度在13 (6+1+6 )到25(12+1+12)之间。这显然有问题,但照这个方式也确实无法保证整个字符串的长度,因为我们无法跨越0-9,为两端0-9A-Za-z- 的量词建立关联,让它们的和为5-11之间。同样,与第5条规则的合并也存在这类问题,因为我们无法确认-的出现位置。看起来,把这5条规则糅合成一个正则表达式,找到能够匹配的文本,真不是件容易的事情。不过,如果我们要做的只是验证,不妨换个思路:我们要匹配的并不是

11、所有的文本,而是文本的开始位置,它后面的文本满足5个条件,而每个条件都可以不用实际匹配任何文本,而用环视来满足。对应5条规则的环视表达式依次是:下面就是寻找这样一个文本起始位置,它后面的文本同时满足这5个条件。实际上,因为锚点并不真正匹配文本,所以多个锚点可以重叠在一起,因此我们完全可以寻找5 个锚点,把它们串联起来:(?=.6, 12$)(?=0-9A-Za-z-*$)(?!-).*(?!-)$)(?=.*0-9)(?!.*-)意思就是:先寻找这样一个字符串起始位置,它之后的字符串满足条件1;然后寻找这样一个字符串其实位置,它之后的字符串满足条件2; 如果能找到5 个这样的字符串起始位置(实

12、际上,因为只有一个字符串起始位置,所以这5 个位置是重叠的),就算验证成功。其实我们也可以不用那么多的括号,只用一个即可:(?=.6, 12$)(?=0-9A-Za-z-*$)(?=(?!-).*(?!-)$)(?=.*0-9)(?!.*-)总结虽然“匹配”是正则表达式的常见操作,但细分起来,“匹配”又可分为提取和验证两种操作。提取时需要照顾准确性和效率,因为此时字符串的起始/结束位置是不确定的,应当添加适当的环视结构,避免匹配了不期望的数据。验证时对效率的要求并不高,因为验证的字符串一般都很短,而且验证的起始/结束位置都是确定的,直接在字符串两端添加和$即可。而且验证有时候要比提取简单得多,我们可以改换思路,改“查找文本”为“查找位置”,针对验证时容许/不容许出现的每一个条件,写出对应的环视功能,作为一个将它们并列在一起。查看文档来源:http:/

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 实用文档 > 统计图表

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报