正则表达式高级用法

引子

上一章分享了正式表达式的入门知识,以及单字符、多字符常用的匹配方法,对于工作维护过程中已经够用,但是有时候只使用基础知识来实现就会比较麻烦,如果使用高级用法就会比较方便很多。
例如:匹配一个HTML文件中两个<B>标签中的文件。
文本内容:

This offer is not available to customers living in <B>AK</B> and <B>HI</B>

从上一章内容的知识可以想到的表达式可能如下:

<[Bb]>.*</[Bb]>

但是这个表达式配置的结果是AK</B> and <B>HI,而不是我们想要的AKHI

懒惰型匹配

引子中的例子中的匹配方式是属于贪婪行为,就是尽可能多的匹配内容,像例子中第一个<B>和最后一个</B>中间都被匹配到了,而不管匹配内容中是否存在</B>。
上一章中讲到的*和+、{m,}都是所谓的“贪婪型”的。在这一节中讲一下与“贪婪型”相反的“懒惰型”,就是匹配尽可能少的内容。

实现很简单,就是在原有“贪婪型”元字符后面加上一个? 号,如下表格

贪婪型元字符 懒惰型元字符
* *?
+ +?
{m,} {m,}?

位置匹配

在现实的系统中一般表达位置的地方就是一个单词的开头以及结尾或者一个字符串的开头或者结尾。
注意这个边界只是一个位置,例如单词边界匹配的是\w\W之间的一个位置

元字符 说明 注意
\b 单词边界,单词的开头或者单词的结尾 回退键的元字符是[\b]
\B 表示非单词边界
^ 字符串的开头位置 放在[]中表示取非操作
$ 字符串结尾位置

扩展:

  • 像egrep中也支持使用\<匹配单词开头位置,使用\>匹配单词结尾位置,但是支持这种元字符的编辑器比较少。
  • (?m)是一个分行匹配模式的记号,放在一个表达式的最前面,会改变字符串位置匹配的行为。^不仅匹配正常的字符串开头还匹配行分隔符(换行符)后面的开始位置;同样$不仅匹配正常的字符串结尾还匹配行分隔符(换行符)后面的结束位置;此用法只有部分正则表达式会支持
选项 描述 支持平台
(?d) Unix中的行 java
(?i) 不区分大小写 PCRE Perl java
(?J) 允许重复的名字 PCRE*
(?m) 多行 PCRE Perl java
(?s) 单行 PCRE Perl java
(?u) Unicode java
(?U) 默认最短匹配,与懒惰型匹配类似 PCRE
(?x) 忽略空格和注释 PCRE Perl Java
(?-...) 复原或关闭选项 PCRE

捕获分组与后向引用

前面的元字符都是对紧挨着前面的一个字符有效,例如表达式the{3}匹配theee字符串,假如我们想匹配连续三个the字符串怎么办呢,这就涉及到子表达式的概念。

子表达式

把一个表达式匹配的内容做为一个单独的元素嵌入到另外一个表达式中,那这个做为独立元素的表达式就是子表达式,需要使用()括起来。这个跟数学的表达式概念很类似。
并且子表达与数学表达式还有一个类似的地方就是,正则表达式的子表达式也可以嵌套使用

本节开头说的那个问题就可以使用子表达式来实现,(the){3}就会匹配thethethe这个字符串。

假如我们再加个条件:我们想匹配连续三个the或者连续三个you,怎么实现?这就是正则表达式的选择操作符,也叫或操作符了

元字符 说明
| 或操作符,两边的表达式都是一个独立的元素,一般放在()中使用

上面的问题就可以使用正则表达式(the|you){3}来表示

捕获分组与后向引用

当一个模式的全部或者部分内容由一对括号括起来时,就对表达式进行了分组(其实就是放在()中的子表达式),并且把分组匹配到内容捕获并且临时存放在内存中。这就是捕获分组,可以在后面表达式中使用就叫后向引用,或者叫回溯引用。
默认情况下,分组是从左到右依次排序从1编号,第一个分组就是1,第二个分组就是2等等。

最开始的时候支持的编号范围是1到9,现在应该已经没有这种限制了。

后向引用很简单就是一个\或者$后面跟相应编号即可。例如\1或者$1就表示引用第一个捕获分组。

命名分组

前面讲捕获分组都是通过位置编号来访问,在perl和python、.NET等语言中还支持对捕获分组命名。这样就比较容易理解

命名语法 描述
(?<name>分组) 命名分组
(?P<name>分组) python中的命名分组
\k<name> Perl中引用命名分组
\k'name' Perl中引用命名分组
\g{name} Perl中引用命名分组
\k{name} .NET中引用命名分组
(?P=name) Python中引用命名分组

非捕获分组

顾名思义,与捕获分组相反,就是不会将分组匹配的内容放在内存中。主要是为了提高性能。
使用方法:在分组的开头加上?:,例如(?:the)

当把非捕获分组语法中的:换成>时,就变成了原子分组(另一种非捕获分组),可以进一步提升性能。因为原子分组会将分组内部的回溯操作关闭。

环视

环视是一种非捕获分组,它根据某个模式之前或者之后的内容要求匹配其他模式。环视也称为零宽度断言。

环视分类 说明 举例
(?=分组) 正前瞻,匹配且要求紧随其后内容为分组匹配的内容 a(?=b),匹配a并且后面坚接着是b的字符串,可以匹配abc但是不匹配acb
(?!分组) 反前瞻,即对正前瞻含义取反,匹配且要求紧随其后内容不为分组匹配的内容 a(?!b),匹配a并且后面坚接着不是b的字符串,可以匹配acb但是不匹配abc
(?<=分组) 正后顾,即对正前瞻方向取反,匹配且要求紧挨着之前的内容为分组匹配的内容 (?<=a)b),匹配b并且前面紧挨着是a的字符串,可以匹配abc但是不匹配cbc
(?<!分组) 反后顾,即对正后顾含义取反,匹配且要求紧挨着之前的内容不为分组匹配的内容 (?<!a)b),匹配b并且前面紧挨着不是a的字符串,可以匹配cbc但是不匹配abc

条件匹配

(?(id/name)yes-pattern|no-pattern)
如果给定的 id 或 name 存在,将会尝试匹配yes-pattern;否则就尝试匹配no-patternno-pattern可选;
例如:email样式匹配(<)?(\w+@\w+(?:\.\w+)+)(?(1)>|$),当<存在时,则最后要匹配>;否则匹配结束符$

参考

《学习正则表达式》
《正则表达式必知必会》

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 161,326评论 4 369
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,228评论 1 304
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 110,979评论 0 252
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,489评论 0 217
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,894评论 3 294
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,900评论 1 224
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,075评论 2 317
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,803评论 0 205
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,565评论 1 249
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,778评论 2 253
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,255评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,582评论 3 261
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,254评论 3 241
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,151评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,952评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,035评论 2 285
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,839评论 2 277

推荐阅读更多精彩内容