正则表达式中的断言(assertions)

正则表达式中的断言(assertions)

1、什么是断言?

广义上理解,断言(assertions),从字面上理解就是,判定,还是。在正则表达式的系统里,也就是匹配或者不匹配。随便写一个正则表达式,都能产生匹配或者不匹配的结果,所以,可以这样说,所有的正则表达式都可以叫断言。
有时候,我们也经常会看到看到这个概念,零宽断言(zero-width assertions)。普通的断言,比如\d+(匹配一个或者多个数字),它所匹配的内容是由长度的;而有些断言比如^$(分别匹配行开头和结尾)匹配的仅仅是一个位置,这样可以理解为它所匹配的内容长度为0。所以,称这类断言为零宽断言(zero-width assertions)。

然而,实际中,好多时候,提到断言,都是指零宽断言(Regular Expressions Explained)。(可以这样简单地理解:其它的断言比较简单,没有什么好说的。。。)所以,有时候,会看到下面的概念:

An assertion is a test on the characters following or preceding the current matching point that does not actually consume any characters.

From: php Assertions

翻译:
断言就是判断当前位置的前后是否匹配,但是不消耗任何字符。

下面是断言的一个解释:

Actually matches characters, but then gives up the match, returning only the result: match or no match. They do not consume characters in the string, but only assert whether a match is possible or not.

From: Lookahead and Lookbehind Zero-Length Assertions

2、断言的分类

正则表达式中右两类断言:Anchors和Lookarounds。

2.1 Anchors

Anchors, or atomic zero-width assertions, cause a match to succeed or fail depending on the current position in the string, but they do not cause the engine to advance through the string or consume characters. The metacharacters listed in the following table are anchors.

Assertion Description Pattern Matches
^ The match must start at the beginning of the string or line. ^\d{3} 901 in 901-333-
$ The match must occur at the end of the string or before \n at the end of the line or string. -\d{3}$ -333 in -901-333
\A The match must occur at the start of the string. \A\d{3} 901 in 901-333-
\Z The match must occur at the end of the string or before \n at the end of the string. -\d{3}\Z -333 in -901-333
\z The match must occur at the end of the string. -\d{3}\z -333 in -901-333
\G The match must occur at the point where the previous match ended. \G\(\d\) (1), (3), (5) in (1)(3)(5)[7](9)
\b The match must occur on a boundary between a \w (alphanumeric) and a \W (nonalphanumeric) character. \b\w+\s\w+\b them theme, them them in them theme them them
\B The match must not occur on a \b boundary. \Bend\w*\b ends, ender in end sends endure lender

From: Anchors in Regular Expressions

2.2 Lookarounds

Example Lookaround Name What it Does
(?=foo) Lookahead Asserts that what immediately follows the current position in the string is foo.
(?<=foo) Lookbehind Asserts that what immediately precedes the current position in the string is foo.
(?!foo) Negative Lookahead Asserts that what immediately follows the current position in the string is not foo.
(?<!foo) Negative Lookahead Asserts that what immediately precedes the current position in the string is not foo.

3、断言的使用举例

这里以IDEA为例,举例说明断言的使用。
在IDEA中新建一个text.txt文本文件,然后输入如下测试文本:

in the house, there is a little horse.
finally, it won over a long race near the small inn.
all above is just a makeup story.

3.1 Lookahead

匹配前面紧跟着“al”的“in”,可以用正则表达式:

in(?=al)

效果如下:


Lookahead

3.2 Lookbehind

匹配后面是“in”的“al”,可以用正则表达式:

(?<=in)al

效果如下:


Lookbehind

3.3 Negative Lookahead

匹配前面没有紧跟着“al”的“in”,可以用正则表达式:

in(?!al)

效果如下:


Negative Lookahead

3.4 Negative Lookbehind

匹配后面不是“in”的“al”,可以用正则表达式:

(?<!in)al

效果如下:


Negative Lookbehind

3.5 组合使用

同时使用前向和后向断言可以实现对匹配内容两侧的控制。
匹配后面是”f“前面是”al“的”in“,可以用正则表达式:

(?<=f)in(?=al)

效果如下:


composition use

匹配后面不是”fin“前面是”ly“的”al“,可以用正则表达式:

(?<!fin)al(?=ly)

效果如下:


composition use 2

3.6 Practice

比如我们有如下的xml文档:

<?xml version="1.0" encoding="UTF-8"?>
<note>
    <item
            class="important">
        <type>Reminder</type>
        <headline>Weekend plan</headline>
        <body>Don't forget swimming this weekend!</body>
    </item>
    <item class="vital">
        <type>Event</type>
        <headline>Exam</headline>
        <body>Exam on tomorrow morning!</body>
    </item>
</note>

(1) 匹配搜索每条item的内容
现在我们想匹配搜索出每条item的内容,可以采用如下的正则表达式:

(?<=<item\s{1,200}class=".{1,200}">\s{1,200})<(.|[\n\r])+?(?=\s+<\/item>)

效果如下图:


Practice 1

在上面的正则表达式中可以看出有写{1,200}。实际上,这里只是用来取代+(相当于{1,},出现1次或者一次以上)。由于这些模式是出现在后向断言的模式(出现在匹配内容的左侧)中,所以不能包含不限定上限次数的模式(可能和具体正则表达式的实现有关系),由于这里不可能高于200次,所以这里用它来取代次数无上限。
这有什么用呢?上图中的红框可以让IDEA选中所有的匹配,这时候,只需要复制粘贴,就可以将所有匹配到的内容一次性全部摘出来。效果如下:

<type>Reminder</type>
        <headline>Weekend plan</headline>
        <body>Don't forget swimming this weekend!</body>
<type>Event</type>
        <headline>Exam</headline>
        <body>Exam on tomorrow morning!</body>

(2) 匹配所有Event的class
现在想匹配所有Event的class,可以使用如下的正则表达式:

".+"(?=>\s+<type>Event</type>)
Practice 2

这里由于用的是前向断言,所以,这里可以采用+这种不设次数上限的匹配模式。

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

推荐阅读更多精彩内容

  • 允许的修饰符 有些修饰符能在所有允许的地方出现, 但并非所有的都这样. 通常, 影响 regex 编译的修饰符(...
    焉知非鱼阅读 1,341评论 0 1
  • 从匹配中返回值 Match 对象 成功的匹配总是返回一个 Match 对象, 这个对象通常也被放进 $/ 中, (...
    焉知非鱼阅读 1,800评论 0 1
  • NAME dnsmasq - A lightweight DHCP and caching DNS server....
    ximitc阅读 2,856评论 0 0
  • 亓茕 千山暮雪 踏破芒鞋 背包的旅程装点人生 过去的倒影回忆中 纵是稚气未脱 也率性可爱了 撷一...
    亓茕阅读 412评论 3 7
  • 深蹲不会占用你很多时间 对于减肥的人来说,一次跑步的时间至少在30分钟左右,甚至1个小时,而进行一次有效的深蹲训练...
    回美法阅读 735评论 0 0