我们都知道,正则表达式可以很方便地对字符串进行匹配、查找、分割等操作。但是,面对看似复杂的符号组合,自己就曾被唬过,感觉这是一种难以理解的语法,所以碰到的时候也就查查对应的正则表达式是表示什么意思,并没有尝试了解。人总是被逼的,轮到自己开发有关字符串的匹配功能的时候,发现使用字符串拆解比对的方式,逻辑上实在很繁杂,不简练更不直观,程序的健壮性也不敢想象。可见,即使某种语言是正交完备的,也不一定能很高效地去表述所有逻辑语境——这个论断和我之前写到的《压缩算法引申》是一致的。这么着,自己也给自己一个机会接触新知识,看了一天正则表达式,并用程序实践之,逐渐感觉渐入佳境。于是用自己的思维方式(物理出身),重新整理正则表达式的精要。

这里,我尝试用数学集合的方式去表述正则表达式,希望能够用几乎人尽皆知的集合方式阐述看似复杂的字符串匹配规则。本文,主要参数正则表达式的基本语法要素,即字符组,为了满足集合表述,这里把字符组成为字符集合。具体分析如下:

1. 普通字符

类似只有单个元素的集合组,每个集合只有一个字符,这个字符可以是字母、汉字、数字、下划线、换行符等。单个字符集合只能表示该字符本身,如正则式“A”所匹配的就是左右只含字母“A”的字符串。用集合运算,即

{A} = {A},{^A} != {A} (这里^是非的意思,映射到集合运算,即为补集的概念)

2. 预定义字符

在正则表达式语法要素中,有一些字符集合是预定义好的,我们可以拿来即用。这些字符集合的划分方式很符合我们平时使用到的字符划分方式。这些预定义的字符集一般是成对出现的,也是使用集合补集的概念。具体如下:

预定义字符

说明

\d和\D

\d表示0到9之间的一个数字,集合表达式为设D={0,1,2,3…9},总集合N={所有字符(视具体编码而定)},则\d表示为A = {a : a∈D}

\D是\d的补集,表示0到9以外的任意一个字符,集合表达式B={b,b∈^D}

\w和\W

\w表示字母、数字、下划线中任意的一个字符,即A={a : a∈[a-zA-Z0-9_]}

\W是\w的补集,即\W表示除字母、数字、下划线之外的任意一个字符

根据不同的编码,这个集合会有所变动,如下说明

在支持ASCII码的语言中,如JavaScript,“\w”等价于[a-zA-Z0-9_] ;
在支持Unicode的语言中,如JAVA,默认情况下,“\w”除可以匹配[a-zA-Z0-9_]外,还可以匹配一些Unicode字符集,如汉字,全角数字等等。

\s和\S

\s表示任意一个空白字符,如空格、制表符、换页符等,\S是\s的补集

注意:上面的预定义字符集合的元素个数都是1,和普通字符一样;并且,我们发现不同语言支持的编码不同,预定义字符所对应的具体内容也不同。这样,我们可以很轻松的写出特定区域电话号码的正则表达式:

0592-\d\d\d\d\d\d\d

备注:正则表达式预定义字符不仅仅上面三类,还有其它小类,这里不予罗列。

3.自定义字符集合

集合区间是个重要的概念,用于表述集合元素的范围。从集合的表示法看,集合一般有两种表示法:①枚举法(列举法)②描述法。我们在写正则表达式的时候往往也需要用到集合区间的概念,也同样可以使用枚举法(如上例,电话号码),也可以使用描述法。我们知道,往往描述法会显得简练,不易遗漏。正则表达式同样有一套区间的表示方法,非常直观,就是[#-&],其中#和&都表示字符元素。当然,也可以使用枚举法,同样是用[]表示,如[xyz]表示x/y/z中的任意一个字符,注意,还是单个字符,即x ∈[表达式]——枚举法还可以用|或语句表示,如[x|y|w]。既然有区间表述,也会有补集的定义。正则表达式的补集定义是这样的[^#-&],表示集合[#-&]的补集。

举例,同样是用电话号码,只查询号码第一位的高于5的电话号码集合,表达式如下

0592-[6-9]\d\d\d\d\d\d,或者0592-[^0-5]\d\d\d\d\d\d。

备注:字符集可以通过[]自定义,仅仅匹配多个字符中的一个

4. 特殊字符

接下来要讲解的是特殊字符,这些特殊字符也是预定义字符,个人觉得目的是为了向完备性和简练性进发。先列表展示一下这些特殊字符

特殊字符

.

匹配换行符以外的任意字符,即[^\n]

^

匹配字符串的开始

$

匹配字符串的末尾

\b

匹配字符串的开始或者末尾

\B

\

转义字符,对上述特殊字符,需要通过该转义字符来取消预定义的特殊意义

上述^、$、\b、\B这四个字符为了满足定位字符串的前后位置;\转义字符,目的就是为了把已经占用的特殊字符转换为正常字符,是为了满足完备。

顺便罗列出量词定义,以便一并解释这些定义的集合意义,如下

量词:就像是计算集合元素个数的聚合函数,类似COUNT(A)——具体的数学表达式给忘了…

量词

S?

表示指定的字符或组S最多出现一次,可以没有

S+

表示指定的字符或组S至少出现一次

S*

表示指定的字符或组S可以出现任意次,包括不出现

{n}

表示指定的字符或组必须出现n次

{m,n}

表示指定的字符或组最少出现m次,最多出现n次

{n,}

表示指定的字符或组最少出现n次,多了不限

有了量词的定义,我们就可以更简练的实现重复性定义的缩写了,这个有点类似数学里的科学计数法。还是那个号码例子,之前我们为了拼接7个数字,需要写7次\b,这个不仅不直观,可能会漏写或者多写,也不便于代码维护。有了量词的定义,就可以用\b{7}表示,这个就非常简练了。再举个例子,有时候我们要匹配的字符串长度是预先未知的,使用*就非常轻松解决这个问题了,比如\w*,表示任意个数的字符拼接的字符串。

回归到字符串的基本定义,一个字符串包含多个字符。使用上述介绍的字符集,基本上是涵盖了所有的字符,即任意字符∈上述定义的集合并集。但是,单纯这样的集合根本不够适用于灵活的正则表达式,即不适合于表示我们想要表述的字符串规则——是的,正则表达式的目的是就是表示一个有规律的字符串。所以,引入量词的目的就是为了满足这个目的。因为,发现没,量词其实有if、for的逻辑。也就说,量词完成了正则表达式的逻辑法则。巧妙的使用量词和巧妙的使用编程语法是一样的,需要一个练习和实战的过程。

具体实战例子会在自定义veLocity模板编辑器的自动联想功能中总结。


个人整理的进阶文章

(二)正则表达式之常用表达式详细解析


备注:本文参考资料主要有《菜鸟成长之路——Java程序员全攻略》之11.2拿下正则式。

一 正则表达式快速入手指南之字符集合表达式包含个人总结的更多相关文章

  1. Html5 canvas实现粒子时钟的示例代码

    这篇文章主要介绍了Html5 canvas实现粒子时钟的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  2. HTML5数字输入仅接受整数的实现代码

    这篇文章主要介绍了HTML5数字输入仅接受整数的实现代码,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  3. ios – 使用大写符号在字符串swift中获取URL的正则表达式

    我尝试在文本中获取URL.所以,在此之前,我使用了这样一个表达式:但是当用户输入带有大写符号的URL时(例如Http://Google.com,它与它不匹配)我遇到了问题.我试过了:但什么都没发生.解决方法您可以使用正则表达式中的i内联标志关闭区分大小写,有关可用正则表达式功能的详细信息,请参阅FoundationFrameworkReference.(?ismwx-ismwx)Flagsetti

  4. 在Xcode4中,你可以更改用于显示隐形字符的字符吗?

    我更喜欢VisualStudio显示隐形的方式……

  5. ios – NSLocalizedString有时会加载字符串,而不是总是

    解决方法如果您的localisable文件中有任何额外的分号,它会构建但无法进行本地化.

  6. ios – 应用程序商店描述特殊字符

    是不是可以在AppStore描述中使用像星星这样的特殊字符了?我得到这个错误:描述不得包含标记语言.说明不得包含以下字符:★提前致谢:)解决方法仍然允许一些unicode字符.以下字符已经过测试并仍然有效:◆√至于现在他们工作正常,但苹果可以随时再次改变条件.

  7. ios – 将数组中的字符转换为整数

    即使我搜索了文档,我似乎无法弄清楚如何做到这一点.我试图弄清楚如何将数组中索引处的字符转换为整数.例如,假设我有一个名为“容器”的字符数组,我无法弄清楚该怎么做:谢谢您的帮助!解决方法Swift并不容易在原始和类型表示之间进行转换.这是一个在此期间应该有所帮助的扩展:这使您可以非常接近您想要的:对于遇到此问题的任何工程师,请参阅rdar://17494834

  8. ios – NSString cString已被弃用.什么是替代品?

    我有另一个新手问题.我写了一段代码,将Nsstring转换为NSMutableData,以模拟一个webService结果.但事实证明,cString已被弃用.你可以帮我更换吗?这是我的代码解决方法>从字符串获取原始字节.>获取UTF8编码中这些字节的长度.>使用dataWithBytes:length:方法创建NSData对象.

  9. ios – 如何在Swift 3中使用正则表达式?

    解决方法我相信.当没有其他选项适用时,将使用.allZeros.因此,使用Swift3,您可以传递一个空的选项列表或省略options参数,因为它默认为无选项:要么请注意,在Swift3中,您不再使用error参数.它现在抛出.

  10. ios – lldb断点在类目标c中的所有方法

    如何使用lldb在ObjectiveC类中的所有方法上自动设置断点?

随机推荐

  1. 法国电话号码的正则表达式

    我正在尝试实施一个正则表达式,允许我检查一个号码是否是一个有效的法国电话号码.一定是这样的:要么:这是我实施的但是错了……

  2. 正则表达式 – perl分裂奇怪的行为

    PSperl是5.18.0问题是量词*允许零空间,你必须使用,这意味着1或更多.请注意,F和O之间的空间正好为零.

  3. 正则表达式 – 正则表达式大于和小于

    我想匹配以下任何一个字符:或=或=.这个似乎不起作用:[/]试试这个:它匹配可选地后跟=,或者只是=自身.

  4. 如何使用正则表达式用空格替换字符之间的短划线

    我想用正则表达式替换出现在带空格的字母之间的短划线.例如,用abcd替换ab-cd以下匹配字符–字符序列,但也替换字符[即ab-cd导致d,而不是abcd,因为我希望]我如何适应以上只能取代–部分?

  5. 正则表达式 – /bb | [^ b] {2} /它是如何工作的?

    有人可以解释一下吗?我在t-shirt上看到了这个:它似乎在说:“成为或不成为”怎么样?我好像没找到’e’?

  6. 正则表达式 – 在Scala中验证电子邮件一行

    在我的代码中添加简单的电子邮件验证,我创建了以下函数:这将传递像bob@testmymail.com这样的电子邮件和bobtestmymail.com之类的失败邮件,但是带有空格字符的邮件会漏掉,就像bob@testmymail也会返回true.我可能在这里很傻……当我测试你的正则表达式并且它正在捕捉简单的电子邮件时,我检查了你的代码并看到你正在使用findFirstIn.我相信这是你的问题.findFirstIn将跳转所有空格,直到它匹配字符串中任何位置的某个序列.我相信在你的情况下,最好使用unapp

  7. 正则表达式对小字符串的暴力

    在测试小字符串时,使用正则表达式会带来性能上的好处,还是会强制它们更快?不会通过检查给定字符串的字符是否在指定范围内比使用正则表达式更快来强制它们吗?

  8. 正则表达式 – 为什么`stoutest`不是有效的正则表达式?

    isthedelimiter,thenthematch-only-onceruleof?PATTERN?

  9. 正则表达式 – 替换..与.在R

    我怎样才能替换..我尝试过类似的东西:但它并不像我希望的那样有效.尝试添加fixed=T.

  10. 正则表达式 – 如何在字符串中的特定位置添加字符?

    我正在使用记事本,并希望使用正则表达式替换在字符串中的特定位置插入一个字符.例如,在每行的第6位插入一个逗号是什么意思?如果要在第六个字符后添加字符,请使用搜索和更换从技术上讲,这将用MatchGroup1替换每行的前6个字符,后跟逗号.

返回
顶部