浅析正则表达式-应用篇

一、前言

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

  浅析正则表达式-原理篇
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

  匹配结果如下图所示:

例子二:匹配下面的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_]+)”:,看一下我们的分析的结果:

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

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

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

例子三:匹配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 [^\(\)]*,对应我们也将匹配的结果放上来:

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

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

  

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

三、结束语

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

时间: 2024-10-29 14:16:30

浅析正则表达式-应用篇的相关文章

浅析正则表达式 — 原理篇

其实这篇文章很久之前就应该发出来,由于种种原因没有发出来,如果这篇文章中有错误,还请大家指出,小弟并改正之,没有学不会的东西,只有不想学的东西,只要功夫深,铁杵磨成针,我的至理名言:吾生也有涯而知也无涯,以有涯随无涯,殆矣.我们只要坚持将其看完,相信大家的正则表达式会有一个提升空间!本文属于.NET正则表达式里面的内容,由于不同语言正则表达式有所不同. 首先先讲解下正则表达式的基础知识: 1.字符串的组成 对于字符串”123“而言,包括三个字符四个位置.如下图所示: 2.占有字符和零宽度 正则表

(非原创)浅析正则表达式

浅析正则表达式-(原理篇) 前言: 其实这篇文章很久之前就应该发出来,由于种种原因没有发出来,如果这篇文章中有错误,还请大家指出,小弟并改正之,没有学不会的东西,只有不想学的东西,只要功夫深,铁杵磨成针,我的至理名言:吾生也有涯而知也无涯,以有涯随无涯,殆矣.我们只要坚持将其看完,相信大家的正则表达式会有一个提升空间!本文属于.NET正则表达式里面的内容,由于不同语言正则表达式有所不同. 首先先讲解下正则表达式的基础知识: 1.字符串的组成 对于字符串"123"而言,包括三个字符四个位

浅析正则表达式-替换原则

浅析正则表达式-替换原则 --> 一.开篇 最近经常用到替换的东西所以就出来整理下,这里要分享的是正则表达式里面的替换原则,首先要声明的是这里提及到的替换原则是.NET里面的正则表达式的替换原则.先看一下替换的定义替换是只能在替换模式中识别的语言元素. 它们使用正则表达式模式定义全部或部分用于替换输入字符串中的匹配文本的文本. 替换模式可以包含一个或多个替换以及本文字符.其实个人总结的替换的大致是这样的,替换的内容永远都是原文本的内容,通过正则表达式匹配出来文本,来通过组名或者组号来进行对原文本

0524.深入浅出理解iOS常用的正则表达式—基础篇[Foundation]

参考资料:cocoachina的zys475481075的文章 几个单词 Regular  ['regj?l?] adj. 定期的:有规律的 Expression [?k'spre?(?)n; ek-] n. 表现,表示 Regular expression 正则表达式 什么是正则表达式? 用一个描述字符串去验证另一个字符串是否符合描述字符串的特征.(不严谨,可以这么理解) 思考:比如表达式"12+",描述的意思是一个1和任意个2组成的字符串,那么'12'.'122'.'122'-.都

【正则表达式介绍篇】 -- 2019-08-16 11:20:46

原文: http://blog.gqylpy.com/gqy/381 "????正则表达式,又称规则表达式.(英语:Regular Expression,在代码中常简写为Regex.regexp或RE),计算机科学的一个概念.正则表达式通常被用来检索.替换那些符合某个模式(规则)的文本. ????许多程序设计语言都支持利用正则表达式进行字符串操作.例如,在Perl中就内建了一个功能强大的正则表达式引擎.正则表达式这个概念最初是由Unix中工具软件(例如sed和grep)普及开的.正则表达式通常缩

【正则表达式介绍篇】 𰧦

原文: http://blog.gqylpy.com/gqy/381 "????正则表达式,又称规则表达式.(英语:Regular Expression,在代码中常简写为Regex.regexp或RE),计算机科学的一个概念.正则表达式通常被用来检索.替换那些符合某个模式(规则)的文本. ????许多程序设计语言都支持利用正则表达式进行字符串操作.例如,在Perl中就内建了一个功能强大的正则表达式引擎.正则表达式这个概念最初是由Unix中工具软件(例如sed和grep)普及开的.正则表达式通常缩

linux 正则表达式基础篇

========  尖括号^ :例:^work:表示以work开头的内容========  $:            work$: 表示以work结尾的内容 ========  ^$:表示空行,不是空格 ========  . 代表且只能代表任意一个字符========  \ 代表转意字符(让代表特殊意义的字符返回原形)例子: \.:只表示小数点========  * 重复0个或者多个前面的字符,不代表所有了========  .* 匹配所有的字符.========  ^.* 任意多个字符开头

python正则表达式练习篇

练习一: 利用who命令输出所有已经登录系统的用户的信息,并把登录名.用户登录时的电传.登录时间.登录地址利用正则表达式分割开来. 数据的格式: %who wesc console Jun 20 20:33 wesc pts/9 Jun 22 01:38 (192.168.0.6) wesc pts/1 Jun 20 20:33 (:0.0) wesc pts/2 Jun 20 20:33 (:0.0) wesc pts/4 Jun 20 20:33 (:0.0) wesc pts/3 Jun

Linux正则表达式——基础篇

一.什么是正则表达式 简单地说,正则表达式就是处理字符串的方法,它是以行为单位进行字符串的处理行为,正则表达式通过一些特殊符号的辅助,可以让用户轻易达到查找.删除.替换某特定字符串的处理程序. 正则表达式基本上是一种"表示法",只要工具程序支持这种表示法,那么该工具程序就可以用来作为正则表达式的字符串处理之用.例如:vi,grep,awk,sed 正则表达式的字符串表达方式依照不同的严谨度而分为基础正则表达式与扩展表达式,扩展表达式除了简单的一组字符串处理外,还可以做组的字符串处理.