正则表达式先行,后向和原子组


314

我在正则表达式主体中找到了这些东西,但是我不知道如何使用它们。有人有例子吗,所以我可以尝试了解它们是如何工作的?

(?!) - negative lookahead
(?=) - positive lookahead
(?<=) - positive lookbehind
(?<!) - negative lookbehind

(?>) - atomic group

18
regex网站为什么没有这样的简单表?相反,它们只有文本块来解释。regular-expressions.info/lookaround.html
白猫

Answers:


850

例子

给定字符串foobarbarfoo

bar(?=bar)     finds the 1st bar ("bar" which has "bar" after it)
bar(?!bar)     finds the 2nd bar ("bar" which does not have "bar" after it)
(?<=foo)bar    finds the 1st bar ("bar" which has "foo" before it)
(?<!foo)bar    finds the 2nd bar ("bar" which does not have "foo" before it)

您也可以将它们结合起来:

(?<=foo)bar(?=bar)    finds the 1st bar ("bar" with "foo" before it and "bar" after it)

定义

展望未来积极 (?=)

在表达式B后面找到表达式A:

A(?=B)

展望未来负面 (?!)

查找表达式B不遵循的表达式A:

A(?!B)

积极看待背后 (?<=)

查找表达式B前面的表达式A:

(?<=B)A

看负面的背后 (?<!)

查找表达式A不在表达式B之前的表达式:

(?<!B)A

原子团 (?>)

原子组退出组并在组内的第一个匹配模式之后丢弃其他模式(禁用回溯)。

  • (?>foo|foot)s应用于foots将会匹配其第一个替代方法foo,然后失败,因为s不会立即跟进,然后由于禁用回溯而停止

非原子团将允许回溯;如果后续的后续匹配失败,它将回溯并使用其他模式,直到找到整个表达式的匹配项或所有可能性已用尽。

  • (foo|foot)s适用于foots

    1. 匹配其第一个替代方案foo,然后由于s未立即跟随而失败foots,并回溯至其第二个替代方案;
    2. 匹配其第二个替代方法foot,然后s立即在中成功,然后foots停止。

一些资源

在线测试人员


1
“查找第二个小节”部分是什么意思?表达式/字符串中只有一个小节。谢谢
ziggy 2014年

2
@ziggy正在测试的字符串是“ foobarbarfoo”。如您所见,字符串中有两个foo和两个bar。
2014年

4
有人可以解释何时需要一个原子团吗?如果我只需要与第一个备选方案匹配,为什么我要给出多个备选方案?
arviman

2
更好的解释关于原子团这个答案。有人可以在这里编辑以完成此教义答案吗?
彼得·克劳斯

5
请注意,当我结束一个需要认真处理正则表达式的项目时,此答案至关重要。这是环顾四周的极好简洁的解释。
汤姆·科夫林

215

环顾四周是零宽度的断言。他们检查正则表达式(基于当前位置的前后方向)(在当前位置的右边或左边),找到匹配项时成功或失败(基于正或负),并丢弃匹配的部分。它们不占用任何字符-紧随其后的正则表达式的匹配项(如果有)将从相同的光标位置开始。

有关更多详细信息,请阅读regular-expression.info

  • 正向前瞻:

句法:

(?=REGEX_1)REGEX_2

仅当REGEX_1匹配时才匹配;匹配REGEX_1后,匹配将被放弃,并在同一位置开始搜索REGEX_2。

例:

(?=[a-z0-9]{4}$)[a-z]{1,2}[0-9]{2,3}

REGEX_1 [a-z0-9]{4}$匹配四个字母数字字符,后跟行尾。
REGEX_2 [a-z]{1,2}[0-9]{2,3}匹配一个或两个字母,后跟两个或三个数字。

REGEX_1确保字符串的长度确实为4,但不占用任何字符,因此对REGEX_2的搜索从同一位置开始。现在,REGEX_2确保该字符串与其他一些规则匹配。如果没有前瞻,它将匹配长度为三或五的字符串。

  • 负前瞻

句法:

(?!REGEX_1)REGEX_2

仅当REGEX_1不匹配时才匹配;否则,不匹配。检查REGEX_1后,将在同一位置开始搜索REGEX_2。

例:

(?!.*\bFWORD\b)\w{10,30}$

前瞻部分检查FWORD字符串中的,如果找到它,则失败。如果找不到FWORD,则预读成功,并且下一部分将验证字符串的长度在10到30之间,并且仅包含单词字符a-zA-Z0-9_

“向后看”类似于“向前看”:它只是在当前光标位置的后面看。某些正则表达式类型(如javascript)不支持后置断言。而且大多数支持它的工具(PHP,Python等)都要求后视部分具有固定的长度。

  • 一旦令牌匹配,原子组基本上会丢弃/忘记该组中的后续令牌。查看此页面以获取原子团的示例

按照您的解释,在JavaScript中似乎不起作用,/(?= source)hello / .exec(“ source ... hummhellosource”)= null。您的解释正确吗?
Helin Wang

@HelinWang那个解释是正确的。您的正则表达式期望同时包含源和问候的字符串!
Amarghosh

@jddxf关心详细吗?
阿玛霍什(Amarghosh)

@Amarghosh我同意“他们检查正则表达式(朝当前位置的右或左-基于前后),在找到匹配项时成功或失败(基于正或负),并丢弃匹配项一部分。”。因此,前瞻应检查当前位置右侧的正则表达式,正前瞻的语法应为x(?= y)
jddxf

@Amarghosh (?=REGEX_1)REGEX_2只会在之后REGEX_2出现时匹配吗? REGEX_1
阿南迪斯

0

快速的环顾四周。
如何区分前瞻和后瞻?花2分钟与我一起游览:

(?=) - positive lookahead
(?<=) - positive lookbehind

假设

    A  B  C #in a line

现在,我们问B,您在哪里?
B有两种解决方法来声明其位置:

一个,B在A的前面,并且C绑定在
第二个,B在C的前面(向前),在A的后面(后面)。

如我们所见,在这两种解决方案中,后面和后面是相反的。
正则表达式是解决方案二。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.