正则表达式前瞻,后观和原子团体

Spi*_*ire 314 regex lookaround

我在我的正则表达式身体中发现了这些东西,但我不知道我能用它们做什么.有人有例子,所以我可以尝试了解它们是如何工作的吗?

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

(?>) - atomic group
Run Code Online (Sandbox Code Playgroud)

sky*_*oot 743

例子

鉴于字符串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)
Run Code Online (Sandbox Code Playgroud)

你也可以把它们结合起来:

(?<=foo)bar(?=bar)    finds the 1st bar ("bar" with "foo" before it and "bar" after it)
Run Code Online (Sandbox Code Playgroud)

定义

展望正面 (?=)

查找表达式A的表达式A:

A(?=B)
Run Code Online (Sandbox Code Playgroud)

展望未来 (?!)

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

A(?!B)
Run Code Online (Sandbox Code Playgroud)

看看积极的背后 (?<=)

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

(?<=B)A
Run Code Online (Sandbox Code Playgroud)

看看消极的背后 (?<!)

查找表达式B不在其中的表达式A:

(?<!B)A
Run Code Online (Sandbox Code Playgroud)

原子团 (?>)

原子组退出组并在组内第一个匹配的模式之后抛弃替代模式(禁用回溯).

  • (?>foo|foot)sapply foots将匹配其第一个替代foo,然后失败,因为s没有立即跟随,并停止回溯被禁用

非原子组将允许回溯; 如果后续匹配失败,它将回溯并使用替代模式,直到找到整个表达式的匹配或所有可能性都用完为止.

  • (foo|foot)s适用于foots:

    1. 匹配其第一个选择foo,然后失败,因为s没有立即跟进foots,并回溯到其第二个替代;
    2. 匹配其第二个选择foot,然后成功s立即跟进foots,并停止.

一些资源

  • @ziggy 被测试的字符串是“foobarbarfoo”。如您所见,字符串中有两个 foo 和两个 bar。 (5认同)
  • 请注意,当我结束一个需要认真处理正则表达式的项目时,此答案至关重要。这是环顾四周的极好而简洁的解释。 (5认同)
  • 有人可以解释什么时候可能需要一个原子团吗?如果我只需要匹配第一个替代方案,为什么我要提供多种替代方案? (4认同)
  • **关于[原子团]的更好解释**,请访问[此答案](/sf/answers/1008859421/)。有人可以在这里编辑以完成此教义答案吗? (2认同)

Ama*_*osh 208

Lookarounds是零宽度断言.他们检查正则表达式(朝向当前位置的右侧或左侧 - 基于前方或后方),找到匹配时成功或失败(基于它是正还是负)并丢弃匹配的部分.它们不消耗任何字符 - 跟随它们的正则表达式的匹配(如果有的话)将从相同的光标位置开始.

阅读regular-expression.info了解更多详情.

  • 积极前瞻:

句法:

(?=REGEX_1)REGEX_2
Run Code Online (Sandbox Code Playgroud)

仅在REGEX_1匹配时匹配; 在匹配REGEX_1之后,匹配被丢弃并且搜索REGEX_2从相同位置开始.

例:

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

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

REGEX_1确保字符串的长度确实为4,但不消耗任何字符,以便搜索REGEX_2从同一位置开始.现在REGEX_2确保该字符串与其他一些规则匹配.如果没有前瞻,它将匹配长度为3或5的字符串.

  • 消极的向前看

句法:

(?!REGEX_1)REGEX_2
Run Code Online (Sandbox Code Playgroud)

仅在REGEX_1不匹配时匹配; 检查REGEX_1后,搜索REGEX_2的位置相同.

例:

(?!.*\bFWORD\b)\w{10,30}$
Run Code Online (Sandbox Code Playgroud)

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

后视类似于前瞻:它只是在当前光标位置后面.像javascript这样的一些正则表达式风格不支持后置断言.大多数支持它的风格(PHP,Python等)要求后视部分具有固定长度.

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