正则表达式高级学习技能 选择自 duduwolf 的 Blog

前言
  Regular Expressions(正则表达式,以下用RE称呼)对小弟来说一直都是神密的处,看到有的大网及的大妈,简单用RE就决解了好几文字的题目,小弟就起了模拟一仿照RE的想法,但小弟天生就是较累一些,总希望看有没有多少快学习的措施,于是小弟又呼吁出Google大神,藉由祂的神力,小弟于网及找到了Jim Hollenhorst先生之稿子,经过了阅读,小弟觉得真是对,所以便召开个小心得报,跟Move-to.Net的冤家分享,希望会也各位大大拉动一丁点在上学RE时之帮忙。Jim Hollenhorst大大文章的网址如下,有要之大大可一直连接。

  The 30 Minute Regex Tutorial By Jim Hollenhorst

  http://www.codeproject.com/useritems/RegexTutorial.asp

  什么是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次描述

  结论
  经过了浩如烟海的事例,及Expresso的辅,相信各位大大对RE有只核心的垂询,网络直达本发成千上万有关于RE的文章,如果各位大大有趣味http://www.codeproject.com 再有为数不少有关RE的连带文章。若大大对写来趣味的话,Jeffrey Friedl的Mastering Regular Expressions很多大大都发出推动(小弟还尚无拜读)。希望籍由这样的感受报告,能吃对RE有兴趣的大妈能缩短学习曲线,当然就是小弟第一潮接触RE,若文章中出啊错或说明的不得了的地方,可倘若乞求各位大大体谅,并请各位大大将用更正的地方mail给小弟,小弟会非常感谢各位大大。

发表评论

电子邮件地址不会被公开。 必填项已用*标注