码迷,mamicode.com
首页 > 其他好文 > 详细

浅析正则表达式-应用篇

时间:2014-10-09 18:45:17      阅读:248      评论:0      收藏:0      [点我收藏+]

标签:style   blog   http   io   os   使用   ar   strong   sp   

一、前言

  时间匆匆流去,我已经来博客园快要两年了,在这里我学会了很多知识,博客园给我带来了知识上的充实和分享的快乐!我现在要分享的是关于正则表达式的一些使用方法,在次声明:必须有一定的正则表达式的基础,否则会有些吃力,如果你对基础不是很了解请翻到这章节:

  浅析正则表达式-原理篇
http://www.cnblogs.com/dwlsxj/p/Regex.html

  浅析正则表达式-柳暗花明又一村篇

http://www.cnblogs.com/dwlsxj/p/Reg.html

  通过上面两篇文章的讲解我相信正则会有一定的基础,并会有一定的提升,我们接下来我们就要讲解本章的重点内容了,正则表达式的使用,这里很多人都会迷茫,我那些元字符之类的我都背的很熟悉,但是就是写不好正则表达式,不知道从哪里下手,我相信通过这篇文章会给大家带来一个思路,我这里说的只是小弟的一些心得,以及这么长时间来对正则使用的一些感悟。

二、应用篇

       我们这里不会说太多理论方面的知识,这样看的也有些厌烦,我从实例出发,主要正则表达式还是应用于.NET平台,其他的没有过的研究,但是这里只是一些思想。

       个人总结方法:

  1. 首先拿到原文本了解匹配的内容(这里就是要匹配的需求)
  2. 分解组成成分,考虑采用那些正则元字符等来写(正则分析)
  3. 根据需求思考所有出现的情况(完整性)

下面从简单例子着手:

例子一:匹配腾讯的QQ号

  我想大家对这个很了解,大家都在用QQ号,都知道QQ号的组成成分应该就是一连串的数字,OK,那么我们这就是对原文本的内容了解,下面我们要考虑的这些数字所有出现的可能腾讯的QQ号是从10000开始也就是从10000数字进行往上增加。那么我们就可以分解出来第一个数字不能是0开头的,而且后面要是以4个数字以上。

  这样我们就分析出来了所有出现的可能性。我们就将正则表达式进行分解。首先我们分解的是首位字符:必须要大于0,那么我们就采用字符类[1-9]这样就搞定了首位字符,那么后面还剩下四位字符,这就好办了,后面四位字符的规则是数字0开始至少有四位那么就可以这样写[0-9]{4,},这样就表示数字从0开始9结束的任意字符至少重复4次。

  正则表达式:[1-9][0-9]{4,}

  原文本:10000

  匹配结果如下图所示:

 

bubuko.com,布布扣

 

例子二:匹配下面的JSON返回的对象内容,匹配所有键值对

  原文本为:{"Dimension1":17.70,"Dimension2":16.70,"Level":"MN","Type":"LVGRM"},

  {"Dimension1":9.30,"Dimension2":11.90,"Level":"MN","Type":"DINRM"},

  {"Dimension1":11.20,"Dimension2":12.00,"Level":"MN","Type":"KITCH"},

  {"Dimension1":12.00,"Dimension2":11.20,"Level":"MN","Type":"EATAR"},

  {"Dimension1":12.20,"Dimension2":13.00,"Level":"MN","Type":"FAMRM"},

  {"Dimension1":15.50,"Dimension2":13.11,"Level":"ABV","Type":"MBDRM"},

  {"Dimension1":8.10,"Dimension2":6.50,"Level":"ABV","Type":"WICLO"},

  {"Dimension1":12.90,"Dimension2":11.50,"Level":"ABV","Type":"BDRM"},

  {"Dimension1":14.30,"Dimension2":14.10,"Level":"ABV","Type":"BDRM"},

  {"Dimension1":8.90,"Dimension2":5.10,"Level":"ABV","Type":"LAUND"},

  {"Dimension1":14.50,"Dimension2":28.70,"Level":"BST","Type":"RECRM"}

  首先我来说明一下这个比如第一行我们是将四对键值对一一匹配出来,Dimension1对应的是17.70,Dimension2对应的是16.70,Level对应的是MN,Type对应的是LVGRM。这样清楚了要匹配内容,这里就是我们理解的要匹配的需求。这里我们就要分析这个正则中所有出现的可能性,我们发现”Dimension1”,” Dimension2”,” Level”,” Type”这些键里面有共同的特点,也就是两边是双引号,中间是字符,通过分段分析之后我们可以得出前面一部分的正则表达式写法是”[a-zA-Z0-9_]+”,注意了这样匹配我们会将双引号也会匹配进去,那么我们就会想到一个东西那就是将引号里面的内容进行分组,我们读取出来的正则直接取出改组的内容即可(这就是考虑问题的完整性),这里我们将前半部分的正则表达式进行完善:”([a-zA-Z0-9_]+)”,好了前半部分的完成了再继续往下分析整个结构,后面跟了一个:那么我们的正则后面也跟一个”([a-zA-Z0-9_]+)”:,看一下我们的分析的结果:

bubuko.com,布布扣

  接下来我们就来分析下一段也就是值得内容,这里我们看到了值分为了两种情况:一种情况是小数,另一种情况是带了双引号的字符,那么我们怎样将这两个组合到一起是一个关键,那么我们就先来找一下他们的共同点,共同点就是他们都可以用正则的\w来进行匹配,那么我们就用字符类将所有可能出现的结果放在字符类里面就会出现[\w.],既然匹配的内容我们已经想办法获取到了,那么我们就会想到这个双引号可有可无,那么我们就想到了懒惰的意思,那么我们就可以使用懒惰来进行完善这个正则表达式:”([a-zA-Z0-9_]+)”:”?([\w.]+)”?这样我们的正则表达式就写好了我们来看一下结果:

bubuko.com,布布扣

  附带一张思维导图,方便大家对上述分析的理解:

bubuko.com,布布扣

  简单的例子咱们这边就不做分享了,有时间自己来研究下就可以了,下面我们来说一个大家都认为用不上的平衡组的例子,第一篇(原理篇)文章的第九讲讲到平衡组里面有一个很明显的案例就是说小括号匹配的问题,这里我就不详细说明了。接下来我们来讲解一个例子。

例子三:匹配SQL语句里面的case….when…语句

  下面是原文本:convert(decimal(18,4),(case replace(f3999 ,‘,‘,‘‘) when ‘‘ then ‘0‘ else isnull(replace(f3999 ,‘,‘,‘‘),‘0‘) end)),

  (case f2733 when ‘house‘ then isnull(f2285,‘‘) else isnull(f2833,‘‘) end),

  (case f2733 when ‘house‘ then isnull(f2576,‘‘) else isnull(f3083,‘‘) end),

  (case f2733 when ‘house‘ then isnull(f2574,‘‘) else isnull(f3081,‘‘) end),

  (case f2733 when ‘house‘ then isnull(f477,‘‘) else isnull(f96,‘‘) end),

  (case f2733 when ‘house‘ then isnull(f714,‘‘) else isnull(f404,‘‘) end),

  下面我们就对这个正则进行分析,首先第一点我们要明白这个里面需求,从字面语句上去理解,看了原文本也应该清楚我们匹配的是case…when…语句,好了我们了解了我们要匹配什么东西,那么我们就来对正则的分析,分段进行分析,进行分析的时候我们能够看到这里面有很多的小括号,如果我们这样协写正则的话”(原文本)”用单纯的两个括号来进行匹配的话仅仅会匹配从左到右最后一次匹配的括号里面的内容,所以这样不是我们想要的结果,这时候我们要想一个整体的思路,这时候我们就要想到一个我们在原理篇谈到的平衡组,用平衡组来进行如果碰到(就压入堆栈,如果碰到)就弹出堆栈,最后判断堆栈里面内容是不是为空的。好的,废话不多说,我们来进行更详细的分析,我们上面已经确定了整体的思路,下面分段进行分析首先我们单独拿出一个SQL出来 case replace(f3999 ,‘,‘,‘‘) when ‘‘ then ‘0‘ else isnull(replace(f3999 ,‘,‘,‘‘),‘0‘) end通过这个语句我们可以先简单的进行分析一下,这里面一共有三对括号,首先要压入堆栈的是最开始的一个括号也就是replace后面的左括号”(”,先进入堆栈中,其次他在进行向后匹配的过程中,这个左括号找到了他的伴侣右括号,就将左括号弹出堆栈,继续往下寻找又碰到了isnull后面的左括号压入堆栈,后面继续往下进行匹配的过程中该左括号A(在堆栈中的)暂时没有找到他的伴侣,却找到了他的情敌左括号B,于是两个左括号不服相继被压入堆栈中进行对抗,不料在半路中左括号B于左括号A在争夺情人的时候,左括号B遇上了他一见钟情的右括号B,左括号B就退出了A于B的爱情Battle,于是爱河里面就剩下了孤零零的左括号A,独自继续寻找自己心爱的人,经过漫长的时间后左括号A终于找寻到了自己心爱的右括号A,两人相伴终生,最后恶魔大人下来整治单身贵族,发现爱河里面已经没有单相思了,恶魔就悄然离去。整体思路就是这样,我们进行分段讲解既然这里面的关键点就在于括号,那么我们就一括号来做划分,第一个左括号之前的内容还是比较容易的,所有组成成分中包含空格,字符两种,这里要抛弃掉关键字段左右括号,那么我们的正则表达式①为:case [^\(\)]*,对应我们也将匹配的结果放上来:

bubuko.com,布布扣

  下面我们就要进入匹配第一个左括号了,我们将这个平衡组的名称取名为battle吧,接下来就是将左括号压入到battle中去,正则如下:(?’battle’\()接下来就是括号里面的内容了,经过我们的分析和详细观察源文本得出一个结果就是这个里面的内容一定不包括左右括号以外的所有内容,那么这个正则就会这样写[^\(\)]*,所以这两句正则组合在一起就是(?’battle’\()[^\(\)]*,而这仅仅是爱情的开始,独自一人在爱河中寻找真爱的人不仅仅只有他一个人,也许还会有很多,那么我们就将这些人划为一类人,那么就仅仅是在数量上的增加了,后面正则会是这样((?’battle’\()[^\(\)]*)+既然我们已经找到了左边的括号那么左边的括号就不会耐得住寂寞独自一人,他会千方百计去寻找他的另一半,那么当他遇到右括号的时候就飞出爱的海洋于相爱的人相伴一生,那么接下来的正则就应该是这样遇到了右括号就将左括号弹出来,如下所示:(?’-battle’\))那么后面跟随的依然是除了左右括号之外的东西[^\(\)]*,最后的正则是(?’-battle’\))[^\(\)]*,前面说了既然爱河中有很多单身的人,那么单身的人选择的人应该也是有很多的但是自己心爱的人只有一个。最后的正则是这样:((?’-battle’\))[^\(\)]*)+,通过左右括号比翼双飞的结果我们可以看出他们是永远的一对,永远都是一起的那么他们就应该是整体的一组成员,对他们进行整合,(((?’battle’\()[^\(\)]*)+((?’-battle’\))[^\(\)]*)+)*也许括号的出现一对都没有,也许会有一对或更多情侣的出现,所以后面加了数量词,既然都成双成对了,那么battle堆栈中就不应该出现单值出现的成员,我们要对battle堆栈进行检验,也就是这句正则(?(battle)(?!))最后将整体的正则进行完整性的整合就是:case[^\(\)]*(((?‘battle‘\()[^\(\)]*)+((?‘-battle‘\))[^\(\)]*)+)*(?(battle)(?!)),这样我们的分析就完整了,下面来看一下整体匹配的结果:

 

bubuko.com,布布扣

  简单将堆栈变化图进行分析:

  

bubuko.com,布布扣

  最后将整体的思维导图整理出来,供大家思考方便:

 

bubuko.com,布布扣

三、结束语

  零零散散的整理了三篇正则表达式的文章,如果有哪里不正确或者不完整的,希望能够指正,通过这几篇文章的总结,我相信看过这些文章的人正则有一定的提升,我自己本身的正则也有一定的提升!

浅析正则表达式-应用篇

标签:style   blog   http   io   os   使用   ar   strong   sp   

原文地址:http://www.cnblogs.com/dwlsxj/p/Regex-3.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!