使用Expresso学习.net正则表达式

什么是RE?
想必各位大大在做文件查找的时侯都有使用过万用字符”*”,比如说想查找在Windows目录下所有的Word文件时,你可能就会用”*.doc”这样的方式来做查找,因为”*”所代表的是任意的字符。RE所做的就是类似这样的功能,但其功能更为强大。

写程序时,常需要比对字符串是否符合特定样式,RE最主要的功能就是来描述这特定的样式,因此可以将RE视为特定样式的描述式,举个例子来说,”\w+”所代表的就是任何字母与数字所组成的非空字符串(non-null string)。在.NET framework中提供了非常强大的类别库,藉此可以很轻易的使用RE来做文字的查找与取代、对复杂标头的译码及验证文字等工作。

学习RE最好的方式就是藉由例子亲自来做做看。Jim Hollenhorst大大也提供了一个工具程序Expresso(来杯咖啡吧),来帮助我们学习RE,下载的网址是http://www.codeproject.com/useritems/RegexTutorial/ExpressoSetup2_1C.zip。

接下来,就让我们来体验一些例子吧。

一些简单的例子
假设要查找文章中Elvis后接有alive的文字符串的话,使用RE可能会经过下列的过程,括号是所下RE的意思:

1. elvis (查找elvis)

上述代表所要查找的字符顺序为elvis。在.NET中可以设定乎略字符的大小写,所以”Elvis”、”ELVIS”或者是”eLvIs”都是符合1所下的RE。但因为这只管字符出现的顺序为elvis,所以pelvis也是符合1所下的RE。可以用2的RE来改进。

2. \belvis\b (将elvis视为一整体的字查找,如elvis、Elvis乎略字符大小写时)
“\b”在RE中有特别的意思,在上述的例子中所指的就是字的边界,所以\belvis\b用\b把elvis的前后边界界定出来,也就是要elvis这个字。

假设要将同一行里elvis后接有alive的文字符串找出来,此时就会用到另外二个特别意义的字符”.”及”*”。”.”所代表就是除了换行字符的任意字符,而”*”所代表的是重复*之前项目直到找到符合RE的字符串。所以”.*”所指的就是除了换行字符外的任意数目的字符数。所以查找同一行里elvis后接有alive的文字符串找出来,则可下如3之RE。

3. \belvis\b.*\balive\b (查找elvis后面接有alive的文字符串,如elvis is alive)

用简单之特别字符就可以组成功能强大的RE,但也发现当使用越来越多的特别字符时,RE就会越来越难看得懂了。


再看看另外的例子
组成有效的电话号码

假使要从网页上收集顾客格式为xxx-xxxx的7位数字的电话号码,其中x是数字,RE可能会这样写。

4. \b\d\d\d-\d\d\d\d (查找七位数字之电话号码,如123-1234)
每一个\d代表一个数字。”-”则是一般的连字符号,为避免太多重复的\d,RE可以改写成如5的方式。

5. \b\d{3}-\d{4} (查找七位数字电话号码较好的方法,如123-1234)
在\d后的{3},代表重复前一个项目三次,也就是相等于\d\d\d。

RE的学习及测试工具 Expresso

因为RE不易阅读及使用者容易会下错RE的特性,Jim大大开发了一个工具软件Expresso,用来帮助使用者学习及测试RE,除了上面所述的网址之外,也可以上Ultrapico网站(http://www.Ultrapico.com)。安装完Expresso后,在Expression Library中,Jim大大把文章的例子都建立在其中,可以边看文章边测试,也可以试着修改范例所下的RE,马上可以看到结果,小弟觉得非常好用。各位大大可以试试。

.NET中RE的基础概念
特殊字符

有些字符有特别的意义,比如之前所看到的”\b”、”.”、”*”、”\d”等。”\s”所代表的是任意空格符,比如说spaces、tabs、newlines等.。”\w”代表是任意字母或数字字符。

再看一些例子吧
6. \ba\w*\b (查找a开头的字,如able)
这RE描述要查找一个字的开始边界(\b),再来是字母”a”,再加任意数目的字母数字(\w*),再接结束这个字的结束边界(\b)。

7. \d+ (查找数字字符串)
“+”和”*”非常相似,除了+至少要重复前面的项目一次。也就是说至少有一个数字。

8. \b\w{6}\b (查找六个字母数字的字,如ab123c)

下表为RE常用的特殊字符

. 除了换行字符的任意字符
\w 任意字母数字字符
\s 任意空格符
\d 任意数字字符
\b 界定字的边界
^ 文章的开头,如”^The'' 用以表示出现于文章开头的字符串为”The”
$ 文章的结尾,如”End$”用以表示出现在文章的结尾为”End”
特殊字符”^”及”$”是用来查找某些字必需是文章的开头或结尾,这在验证输入是否符合某一样式时特别用有,比如说要验证七位数字的电话号码,可能会输入如下9的RE。

9. ^\d{3}-\d{4}$ (验证七位数字之电话号码)

这和第5个RE相同,但其前后都无其它的字符,也就是整串字符串只有这七个数字的电话号码。在.NET中如果设定Multiline这个选项,则”^”和”$”会每行进行比较,只要某行的开头结尾符合RE即可,而不是整个文章字符串做一次比较。

转意字符(Escaped characters)

有时可能会需要”^”、”$”单纯的字面意义(literal meaning)而不要将它们当成特殊字符,此时”\”字符就是用来移除特殊字符特别意义的字符,因此”\^”、”\.”、”\\”所代表的就是”^”、”.”、”\”的字面意义。

重复前述项目

在前面看过”{3}”及”*”可以用来重复前述字符,之后我们会看到如何用同样的语法重复整个次描述(subexpressions)。下表是使用重复前述项目的一些方式。

* 重复任意次数
+ 重复至少一次
? 重复零次或一次
{n} 重复n次
{n,m} 重复至少n次,但不超过m次
{n,} 重复至少n次

再来试一些例子吧

10. \b\w{5,6}\b (查找五个或六个字母数字字符的字,如as25d、d58sdf等)
11. \b\d{3}\s\d{3}-\d{4} (查找十个数字的电话号码,如800 123-1234)
12. \d{3}-\d{2}-\d{4} (查找社会保险号码,如 123-45-6789)
13. ^\w* (每行或整篇文章的第一个字)
在Espresso可试试有Multiline和没Multiline的不同。

匹配某范围的字符

有时需要查找某些特定的字符时怎么辨?这时中括号”[]”就派上了用场。因此[aeiou]所要查找的是”a”、”e”、”i”、”o”、”u”这些元音,[.?!]所要查找的是”.”、”?”、”!”这些符号,在中括号中的特殊字符的特别意义都会被移除,也就是解译成单纯的字面意义。也可以指定某些范围的字符,如”[a-z0-9]”,所指的就是任意小写字母或任意数字。

接下来再看一个比较初复杂查找电话号码的RE例子

14. \(?\d{3}[( ] \s?\d{3}[- ]\d{4} (查找十位数字之电话号码,如(080) 333-1234 )

这样的RE可查找出较多种格式的电话号码,如(080) 123-4567、511 254 6654等。”\(?”代表一个或零个左小括号”(“,而”[( ]”代表查找一个右小括号”)”或空格符,”\s?”指一个或零个空格符组。但这样的RE会将类似”800) 45-3321”这样的电话找出来,也就是括号没有对称平衡的问题,之后会学到择一(alternatives)来决解这样的问题。

不包含在某特定字符组里(Negation)

有时需要查找在包含在某特定字符组里的字符,下表说明如何做类似这样的描述。

\W 不是字母数字的任意字符
\S 不是空格符的任意字符
\D 不是数字字符的任意字符
\B 不在字边界的位置
[^x] 不是x的任意字符
[^aeiou] 不是a、e、i、o、u的任意字符

15. \S+ (不包含空格符的字符串)

择一(Alternatives)

有时会需要查找几个特定的选择,此时”|”这个特殊字符就派上用场了,举例来说,要查找五个数字及九个数字(有”-”号)的邮政编码。

16. \b\d{5}-\d{4}\b|\b\d{5}\b (查找五个数字及九个数字(有”-”号)的邮政编码)

在使用Alternatives时需要注意的是前后的次序,因为RE在Alternatives中会优先选择符合最左边的项目,16中,如果把查找五个数字的项目放在前面,则这RE只会找到五个数字的邮政编码。了解了择一,可将14做更好的修正。

17. (\(\d{3}\)|\d{3})\s?\d{3}[- ]\d{4} (十个数字的电话号码)

群组(Grouping)

括号可以用来介定一个次描述,经由次描述的介定,可以针对次描述做重复或及他的处理。

18. (\d{1,3}\.){3}\d{1,3} (寻找网络地址的简单RE)

此RE的意思第一个部分(\d{1,3}\.){3},所指的是,数字最小一位最多三位,并且后面接有”.”符号,此类型的共有三个,之后再接一到三位的数字,也就是如192.72.28.1这样的数字。

但这样会有个缺点,因为网络地址数字最多只到255,但上述的RE只要是一到三位的数字都是符合的,所以这需要让比较的数字小于256才行,但只单独使用RE并无法做这样的比较。在19中使用择一来将地址的限制在所需要的范围内,也就是0到255。

19. ((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?) (寻找网络地址)

有没有发觉RE越来越像外星人说的话了?就以简单的寻找网络地址,直接看RE都满难理解的哩。

Expresso Analyzer View

Expresso提供了一个功能,它可以将所下的RE变成树状的说明,一组组的分开说明,提供了一个好的除错环境。其它的功能,如部分符合(Partial Match只查找反白RE的部分)及除外符合(Exclude Match只不查找反白RE的部分)就留给各位大大试试啰。

当次描述用括号群组起来时,符合次描述的文字可用在之后的程序处理或RE本身。在预设的情型下,所符合的群组是由数字命名,由1开始,由顺序是由左至右,这自动群组命名,可在Expresso中的skeleton view或result view中看到。

Backreference是用来查找群组中抓取的符合文字所相同的文字。举例来说”\1”所指符合群组1所抓取的文字。

20. \b(\w+)\b\s*\1\b (寻找重复字,此处说的重复是指同样的字,中间有空白隔开如dog dog这样的字)
(\w+)会抓取至少一个字符的字母或数字的字,并将它命名为群组1,之后是查找任意空格符,再接和群组1相同的文字。

如果不喜欢群组自动命名的1,也可以自行命名,以上述例子为例,(\w+)改写为(?<Word>\w+),这就是将所抓取的群组命名为Word,Backreference就要改写成为\k<Word>
21. \b(?<Word>\w+)\b\s*\k<Word>\b (使用自行命名群组抓取重复字)

使用括号还有许多特别的语法元素,比较通用的列表如下:

抓取(Captures)
(exp) 符合exp并抓取它进自动命名的群组
(?<name>exp) 符合exp并抓取它进命名的群组name
(?:exp) 符合exp,不抓取它
Lookarounds
(?=exp) 符合字尾为exp的文字
(?<=exp) 符合前缀为exp的文字
(?!exp) 符合后面没接exp字尾的文字
(?<!exp) 符合前面没接exp前缀的文字
批注Comment
(?#comment) 批注

Positive Lookaround

接下来要谈的是lookahead及lookbehind assertions。它们所查找的是目前符合之前或之后的文字,并不包含目前符合本身。这些就如同”^”及”\b”特殊字符,本身并不会对应任何文字(用来界定位置),也因此称做是zero-width assertions,看些例子也许会清楚些。

(?=exp)是一个”zero-width positive lookahead assertion”。它指的就是符合字尾为exp的文字,但不包含exp本身。

22. \b\w+(?=ing\b) (字尾为ing的字,比如说filling所符合的就是fill)
(?<=exp)是一个”zero-width positive lookbehind assertion”。它指的就是符合前缀为exp的文字,但不包含exp本身。

23. (?<=\bre)\w+\b (前缀为re的字,比如说repeated所符合的就是peated)
24. (?<=\d)\d{3}\b (在字尾的三位数字,且之前接一位数字)
25. (?<=\s)\w+(?=\s) (由空格符分隔开的字母数字字符串)

Negative Lookaround

之前有提到,如何查找一个非特定或非在特定群组的字符。但如果只是要验证某字符不存在而不要对应这些字符进来呢?举个例子来说,假设要查找一个字,它的字母里有q但接下来的字母不是u,可以用下列的RE来做。

26. \b\w*q[^u]\w*\b (一个字,其字母里有q但接下来的字母不是u)

这样的RE会有一个问题,因为[^u]要对应一个字符,所以若q是字的最后一个字母,[^u]这样的下法就会将空格符对应下去,结果就有可能会符合二个字,比如说”Iraq haha”这样的文字。使用Negative Lookaround就能解决这样的问题。

27. \b\w*q(?!u)\w*\b (一个字,其字母里有q但接下来的字母不是u)
这是”zero-width negative lookahead assertion”。

28. \d{3}(?!\d) (三个位的数字,其后不接一个位数字)

同样的,可以使用(?<!exp),”zero-width negative lookbehind assertion”,来符合前面没接exp前缀的文字符串。

29. (?<![a-z ])\w{7} (七个字母数字的字符串,其前面没接字母或空格)

30. (?<=<(\w+)>).*(?=<\/\1>) (HTML卷标间的文字)
这使用lookahead及lookbehind assertion来取出HTML间的文字,不包括HTML卷标。

请批注(Comments Please)
括号还有个特殊的用途就是用来包住批注,语法为”(?#comment)”,若设定”Ignore Pattern Whitespace”选项,则RE中的空格符当RE使用时会乎略。此选项设定时,”#”之后的文字会乎略。

31. HTML卷标间的文字,加上批注

(?<=  #查找前缀,但不包含它
<(\w+)> #HTML标签
)       #结束查找前缀
.*      #符合任何文字
(?=     #查找字尾,但不包含它
<\/\1>  #符合所抓取群组1之字符串,也就是前面小括号的HTML标签
)       #结束查找字尾

寻找最多字符的字及最少字符的字(Greedy and Lazy)
当RE下要查找一个范围的重复时(如”.*”),它通常会寻找最多字符的符合字,也就是Greedy matching。举例来说。

32. a.*b  (开始为a结束为b的最多字符的符合字)

若有一字符串是”aabab”,使用上述RE所得到的符合字符串就是”aabab”,因为这是寻找最多字符的字。有时希望是符合最少字符的字也就是lazy matching。只要将重复前述项目的表加上问号(?)就可以把它们全部变成lazy matching。因此”*?”代表的就是重复任意次数,但是使用最少重复的次数来符合。举个例子来说:

33. a.*?b (开始为a结束为b的最少字符的符合字)

若有一字符串是”aabab”,使用上述RE第一个所得到的符合字符串就是”aab”再来是”ab”,因为这是寻找最少字符的字。

*? 重复任意次数,最少重复次数为原则
+? 重复至少一次,最少重复次数为原则
?? 重复零次或一次,最少重复次数为原则
{n,m}? 重复至少n次,但不超过m次,最少重复次数为原则
{n,}? 重复至少n次,最少重复次数为原则

还有什么没提到呢?

到目前为止,已经提到了许多建立RE的元素,当然还有许多元素没有提到,下表整理了一些没提到的元素,在最左边的字段的数字是说明在Expresso中的例子。

# 语法 说明

\a Bell 字符
\b 通常是指字的边界,在字符组里所代表的就是backspace
\t Tab

34 \r Carriage return

\v Vertical Tab
\f From feed

35 \n New line
 \e Escape

36 \nnn ASCII八位码为nnn的字符

37 \xnn 十六位码为nn的字符

38 \unnnn Unicode为nnnn的字符

39 \cN Control N字符,举例来说Ctrl-M是\cM

40 \A 字符串的开始(和^相似,但不需籍由multiline选项)

41 \Z 字符串的结尾
\z 字符串的结尾

42 \G 目前查找的开始

43 \p{name} Unicode 字符组名称为name的字符,比如说\p{Lowercase_Letter} 所指的就是小写字
(?>exp) Greedy次描述,又称之为non-backtracking次描述。这只符合一次且不采backtracking。

44 (?<x>-<y>exp)

or (?-<y>exp) 平衡群组。虽复杂但好用。它让已命名的抓取群组可以在堆栈中操作使用。(小弟对这个也是不太懂哩)

45 (?im-nsx:exp) 为次描述exp更改RE选项,比如(?-i:Elvis)就是把Elvis大乎略大小写的选项关掉

46 (?im-nsx) 为之后的群组更改RE选项。
(?(exp)yes|no) 次描述exp视为zero-width positive lookahead。若此时有符合,则yes次描述为下一个符合标的,若否,则no 次描述为下一个符合标的。
(?(exp)yes) 和上述相同但无no次描述
(?(name)yes|no) 若name群组为有效群组名称,则yes次描述为下一个符合标的,若否,则no 次描述为下一个符合标的。

47 (?(name)yes) 和上述相同但无no次描述

转载于:https://www.cnblogs.com/richardli79/archive/2007/05/16/748985.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/277045.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据结构与算法学习笔记之 从0编号的数组

数据结构与算法学习笔记之 从0编号的数组前言数组看似简单&#xff0c;但掌握精髓的却没有多少&#xff1b;他既是编程语言中的数据类型&#xff0c;又是最基础的数据结构&#xff1b;一个小问题&#xff1a;为什么数据要从0开始编号&#xff0c;而不是 从1开始呢&#xff1f;正…

JAVA四种基本排序总结

JAVA四种基本排序,包括冒泡法,插入法,选择法,SHELL排序法.其中选择法是冒泡法的改进,SHELL排序法是 插入法的改进.所以从根本上来说可以归纳为两种不同的排序方法:即:插入法&#xff06;冒泡法一 插入法:遍历排序集合&#xff0c;每到一个元素时&#xff0c;都要将这个元素与所…

Windows 故障转移+Hyper-V 虚机自动迁移高 可用

Windows 故障转移Hyper-V 虚机自动迁移高 可用 Windows 故障转移Hyper-V 虚机自动迁移高... 1一、系统原理... 31.1 高效率的 VMbus 架构... 31.2 完美支持 Linux 系统... 4二、架构拓朴... 52.1 网络及系统架构拓朴... 52.2 域结构拓朴... 5三、实验资源列表... 63.1 网络设备…

MSSqlServer基础学习01

1.新建登陆用户名&#xff0c;须赋予数据库访问权限方可访问已有的数据库&#xff0c;可以参考如下图片转载于:https://www.cnblogs.com/MyVision/p/11242417.html

js,java时间处理

1.JS获取时间格式为“yyyy-MM-dd HH:mm:ss”的字符串 function getTimeStr(){var myDate new Date();var year myDate.getFullYear(); //获取完整的年份(4位,1970-????)var month myDate.getMonth(); //获取当前月份(0-11,0代表1月)month month > 9 ? month : &quo…

框架和模式

1&#xff0e;什么是模式&#xff1f; 模式&#xff0c;即pattern。其实就是解决某一类问题的方法论。你把解决某类问题的方法总结归纳到理论高度&#xff0c;那就是模式。 Alexander给出的经典定义是&#xff1a;每个模式都描述了一个在我们的环境中不断出现的问题&#xff0c…

人月神话第三章

对于效率和概念的完整性来说&#xff0c;最好由少数干练的人员来设计和开发&#xff0c; 而对于大型系统&#xff0c; 则需要大量的人手&#xff0c; 以使产品能在时间上满足要求。 文章参照外科手术队伍对10个人的编程队伍进行专业化的角色分工。并为如何运作做出详细说明。…

评上了7月份的Microsoft MVP

昨天晚上觉得困&#xff0c;于是躺到床上去休息了一会儿&#xff0c;没想到醒来以后就发现了一封信&#xff0c;告诉我当选了7月份的MVP&#xff08;我们的Cat Chen也同样当选了&#xff0c;园子里肯定还有其它朋友&#xff09;。自从去年9月份登陆博客园以来&#xff0c;写技术…

javascript删除数组,索引出现问题解决办法。

var data [{ isRemove: 0, name: "项目1" },{ isRemove: 1, name: "项目2" },{ isRemove: 1, name: "项目3" },{ isRemove: 0, name: "项目4" },{ isRemove: 0, name: "项目5" },{ isRemove: 0, name: "项目6" }…

知识点 - 学习过程中积累

优化数据库查询访问&#xff1a;使用存储过程&#xff0c;利用连接池打开关闭数据库&#xff1b;操作数据是&#xff0c;尽量避免装箱&#xff1b;数据库中为<NULL>的字段&#xff0c;sql语句中用is null读取&#xff1b;开发复合控件的主要步骤&#xff1a;1&#xff09…

Mircosoft 正式把Windows Mobile改名为Windows Phone,你会因此而购买Windows Phone吗?

简介 本文讲述Windows Phone改名事件&#xff0c;以及Windows Phone发展历史和今后发展策略的想法。 事件 今天下班的时候看报纸&#xff0c;有一段新闻关于昨天(2009年10月6日)Mircosoft正式使用Windows Phone这个名字。我去到原先Windows Mobile的主页&#xff0c;已经全部由…

【课后服务】20181022切蛋糕

权当抛砖引玉吧&#xff0c;掌握记搜的方法最重要。 #include<iostream> #include<cstring> #include<cstdio> using namespace std; int n,m,k; bool book[21][21]; int cake[21][21]; int dp[21][21][21][21]; int yt(int x,int y,int w,int h)//返回蛋糕…

我也来记录我的一些开发心得和笔记!

博客园&#xff0c;我来了&#xff01; 转载于:https://www.cnblogs.com/rose2007/archive/2007/07/11/814435.html

经典vim插件功能说明、安装方法和使用方法介绍(已更新)

1 # 2 转载请注明出处: http://blog.csdn.net/tge7618291 http://nuoerlz.is-programmer.com 8 # 9 1. 查看 key 相关信息说明的命令 :help keycodes 10 11 # 12 2. ctags 13 (1). 帮助手册查看 14 :help usr_29 15 16 (2). 功能 17 ctags的功能, 只要在unix/lin…

【哈利波特】Sherbert Lemon对HP的解读之11

NINEScar FaceThe characteristics of Harry’s scar change considerably.PS/SS – BurningQUOTEHarry, who was starting to feel warm and sleepy, looked up at the High Table again. Hagrid was drinking deeply from his goblet. Professor McGonagall was talking to P…

Linux 下, npm i 老是被killed 已杀死

2019独角兽企业重金招聘Python工程师标准>>> node&#xff1a;v8.12.0 npm v6.4.1 npm i 安装到一半会报这样到错误&#xff0c;并终止&#xff1a; npm WARN deprecated socks1.1.10: If using 2.x branch, please upgrade to at least 2.1.6 to avoid a serious …

(转)创建X509证书,并获取证书密钥的一点研究

创建X509证书&#xff0c;并获取证书密钥的一点研究 作者&#xff1a;肖波 个人博客&#xff1a;http://blog.csdn.net/eaglet ; http://www.cnblogs.com/eaglet 2007/7 南京 背景 服务器SSL数字证书和客户端单位数字证书的格式遵循 X.509 标准。 X.509 是由国际电信联盟&#…

css样式优先级计算规则

css样式的优先级分为引入优先级和声明优先级。 引入优先级 引入样式一般分为外部样式&#xff0c;内部样式&#xff0c;内联样式。 外部样式&#xff1a;使用link引入的外部css文件。 内部样式&#xff1a;使用style标签书写的css样式。 内联样式&#xff1a;直接书写在html标签…

phpstudy-5.6.27-nts  安装redis扩展

2019独角兽企业重金招聘Python工程师标准>>> redis扩展安装流程 第一步&#xff1a; 首先直接查看一下phpinfo()的信息 找到下面两条信息 Architecturex86PHP Extension BuildAPI20131226,NTS,VC11Loaded Configuration FileD:\phpStudy\php\php-5.6.27-nts\php.ini…

用DDA Convolution和Perlin Noise来模拟水粉画笔触

在西方&#xff0c;水彩画和水粉画是可以统称为Watercolor的,水粉画通常也称为不透明水彩画或树胶水彩画&#xff08;Gouache&#xff09;&#xff0c;两者既有相似之处&#xff0c;又有所区别。水粉画是以水作为媒介&#xff0c;这一点&#xff0c;它与水彩画是相同的。所以&a…