正则表达式小结

上个公司的项目是个视频直播即时聊天的APP,聊天内容有文字,并且文字分好几个部分例如“某某人对某某人说:blabla......”这就已经三个部分了(某某人,某某人,说的内容),每个部分按照需求文字的颜色还要不一样;除此之外,还有表情,当然服务端发过来的都是带有标识的文字,比如一个微笑表情,服务端过来的是这样的:[微笑],你没有看错,是汉字,哎!不说了。当时作的时候用的正则表达式去抠字符串,现在记一下吧,我这人脑子里存不了东西。
  正则表达式我的理解就像央视的一个节目《墙来了》,被匹配的字符串就是那些搞怪的参赛者,正则表达式就是墙上面的形状轮廓,匹配的过程就是人摆出的形状和墙上的轮廓是否契合。

精确匹配和字符转义

就是匹配字符或字符串本身,例如Hello,就是要匹配Hello(好傻的表达,知道这个意思就行)。不过一些字符在正则表达式里有特别的含义,匹配这些字符本身,就需要借助“\”转义为普通字符,比如.在正则表达式中表示除换行符外的任意字符。那要匹配.本身,就这样了“\.”,That's it。

元字符

不废话,看表格最清楚了:

元字符 匹配内容
. 匹配除换行符以外的任意字符
\w 匹配字母或数字或下划线或汉字
\s 匹配任意的空白字符(空格、制表符、换页符、换行符、回车符等)
\d 匹配任意数字
\b 匹配单词的开始或结束位置
^ 匹配行或字符串开始位置、在字符类中取反
$ 匹配行或字符串结束位置

重复匹配

现在假如匹配5个a,这么写aaaaa有点不那么讲究,这么写a{5}就舒服多了。当然在重复匹配里也有像元字符一类表示特定重复匹配次数的字符,看表就明白了:

重复匹配规则 说明
* 重复匹配零次或更多次
+ 重复匹配一次或更多次
? 重复匹配零次或者一次
{n} 重复匹配n次
{n,} 重复匹配n次或更多次
{n,m} 重复匹配n到m次

字符类

可以看出元字符定义了一个匹配范围(字符或者位置)。通过字符类我们也可以定义一个匹配范围,很简单,快使用[]。比如我们现在匹配abcd这个范围的字符串就可以这样写[abcd]。ok,那么现在定义大写英文字母这个匹配范围,该如何是好?[A-Z],That't it!不用解释那个迷人的-,你该知道ta的用处了。来个例子定义js变量命名规范的正则^[a-zA-Z\_\$][a-zA-Z0-9\_\$]*

取反

还记得那个^吗?ta在字符类中还有别的含义,看个例子[^a-z]表示除了小写英文字母外其它的字符,在字符类中^还表示取这个字符类相反的匹配范围。字符类可以这样取反,元字符也有相对应的元字符用于对该元字符取反(好厉害的表达水准),而且这样的元字符是非常有规律的,看表找一下呗:

取反元字符 匹配说明
\W 匹配任意不是字母,数字,下划线,汉字的字符
\S 匹配任意不是空白符的字符
\D 匹配任意非数字的字符
\B 匹配不是单词开始或结束的位置

分支条件

这个名字也是看其他人的,不过管他呢。现在有这样一个需求:有a,b两个匹配范围,通过组合就会有4种匹配范围了(a,b,ab,ba),如果一个字符串满足这4种的任一种都算匹配成功。怎么搞?快使用|,这么写:a|b|ab|ba。That's it!

分组及后向引用

看到现在你大概也感觉到不管是元字符,还是字符类,ta们(-:瞧瞧这中西合璧的语言风格:-)都定义了一个字符匹配的范围,别的情况还好,但是当重复匹配一组字符的时候就有困难了。例如重复匹配abc三次,不好弄了吧,还是快使用()吧,(abc){3}。就是这么简单,就是这么酸爽。
  上面只是()的一个非常小的用法。下面看大招,一个()就是一个组(匹配小括号字符除外啊),并分配有组号。默认情况下,从左向右,以(为标记,第一个(组号为1,然后依次类推。这个组号有啥用,可以引用成功匹配组号对应组定义的规则的字符串内容,注意加重的文字,不是引用组号对应组的匹配规则,而是成功匹配这个规则的字符串本身。怎么引用呢,使用\组号
  别废话,说例子吧!
  \b([a-zA-Z]+)\b\s+\1\b,这个正则分三部分:\b([a-zA-Z]+)\b\s\1\b。现在有Mookaka匹配第一部分,然后一个空白符Mookaka,之后\1就引用第一部分那个分组匹配成功的字符串也就是Mookaka,所以整个正则可以匹配像Mookaka Mookaka这样的字符串。
  当然像1,2这样的组号看不出所表达的意义,我们也可以自己指定组号,像这样(?<你的组号>匹配规则)或者(?\你的组号`匹配规则)。当然有时你不需要什么这个分组啊,引用什么的,就只是想单纯的重复匹配一组字符串,可以这样写**(?:匹配规则)`**,这样只匹配规则,不分配组号,也不捕获成功匹配的字符串内容。

零宽断言

不纠结这个名字,知道这个名词指的是什么就行。先举一个例子,大家都知道QQ邮箱的格式一般前面是10位数字,然后是@qq.com,现在我们有一批邮箱地址,想从这些地址中抠出qq号,我们只要qq号,后面什么@qq.com就不要了,于是你写了一个真正\d{10,11}@qq\.com,之后你获得的是完整的邮箱地址,接下来你会在构建一个正则什么的来取这个地址字符串前面的qq号。能不能定义这样一种正则,要取的字符串本身匹配定义的正则,并且以这个字符串为基点ta的前面或后面也匹配定义的其它正则,零宽断言就是干这事的。例如上面的例子,构建正则\d{10,11}(?=@qq\.com),那么这个正则就直接取前面的qq号。
  零宽断言就是定义要获取的匹配正则的字符串位置的前面或后面需要符合的规则,但符合这个规则的字符串不在取出字符串之列,看表格(这里把那个要获取的字符串称为基点字符串吧):

表达式 说明
(?=RegExp) 基点字符串后跟符合RegExp定义的内容
(?<=RegExp) 基点字符串前面跟符合REgExp定义的内容
(?!RegExp) 基点字符串后面不跟符合RegExp定义的内容
(?<!RegExp) 基点字符串前面不跟符合RegExp定义的内容

贪婪、懒惰匹配

一般情况下,正则表达式里含有重复,那么在使整个正则表达式能够匹配的前提下,重复将会匹配尽可能多的字符。看这样一个正则^(\d+)(0*)$,注意这里有两个分组,如果102300和ta匹配,第一个组获取102300,第二个组什么也捕获不了,但实际上我们希望组一获取1023,组二捕获剩下的零的。为了不让正则在有重复匹配时太过贪心,在可能发生贪婪匹配的后面加个?,That's is。看表格:

懒惰匹配 说明
*? 重复匹配任意次,但尽可能少重复
+? 重复1次或更多次,但尽可能少重复
?? 重复0次或1次,但尽可能少重复
{n,m}? 重复n次到m次,但尽可能少重复
{n,}? 重复n次以上,但尽可能少重复

注释

还可以给正则加注释,开发APP的时候用了很多正则表达式,有的还很长有点复杂,开发组老大看着头晕,提示正则可以加注释。但是实际上也没好多上,反而正则更长看着更难受。用(?#你的注释)的方式来加注释,看个例子:2[0-4]\d(?#200-249)|25[0-5](?#250-255)|[01]?\d\d?(?#0-199)

平衡组

假如现在我要从一个字符串中提取数学表达式,那么提取的字符串中如果有括号,左括号和右括号的数量是一样的。先看一下下面的规则:

  • (?'group'RegExp) 把匹配RegExp规则的内容命名为 group,并压入栈中。
  • (?'-group'RegExp) 假如匹配RegEXp规则,把最后压入栈且名为group的捕获内容弹出,如果栈是空的,则这个分组的匹配失败。
  • (?(group)RegExp1|RegExp2) 假如栈上有名为group的捕获内容,就接着匹配RegExp1表达式,否则继续匹配RegExp2表达式。
  • (?!) 总是匹配失败。
      总是匹配失败,搞什么?
      匹配失败时,正则表达式引擎会进行回溯也就是放弃最前面或最后面的已经捕获了的字符,使整个表达式得到匹配。
      这样用(?'bracket' \(),遇到左括号就在栈里面记一下,遇到右括号,就用(?'-bracket'\)),把对应的左括号在栈中的记录去掉;如果左括号比右括号多那么最后栈中一定还有记录,那么用(?(bracket)(?!))故意匹配失败,让正则表达式引擎去掉结果字符串中在栈里有记录的字符串。这样左右括号的数量就平衡了。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,045评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,114评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,120评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,902评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,828评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,132评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,590评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,258评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,408评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,335评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,385评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,068评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,660评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,747评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,967评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,406评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,970评论 2 341

推荐阅读更多精彩内容

  • 推荐几个正则表达式编辑器 Debuggex :https://www.debuggex.com/ PyRegex:...
    木易林1阅读 11,437评论 9 151
  • 几个正则表达式编辑器 Debuggex :https://www.debuggex.com/ PyRegex:ht...
    没技术的BUG开发攻城狮阅读 4,578评论 0 23
  • 正则表达式到底是什么东西?字符是计算机软件处理文字时最基本的单位,可能是字母,数字,标点符号,空格,换行符,汉字等...
    狮子挽歌阅读 2,132评论 0 9
  • 初衷:看了很多视频、文章,最后却通通忘记了,别人的知识依旧是别人的,自己却什么都没获得。此系列文章旨在加深自己的印...
    DCbryant阅读 3,979评论 0 20
  • 学员聚会,酒过三巡,让大家介绍下自己,简单的讲下过往的人生经历。 被称为老大哥的人说,年轻时,因为一次失误,跟爱好...
    自由的申申阅读 281评论 0 1