【问题标题】:Regex lookahead, lookbehind and atomic groups正则表达式前瞻、后瞻和原子组
【发布时间】:2011-02-27 17:48:51
【问题描述】:

我在我的正则表达式正文中发现了这些东西,但我不知道我可以用它们做什么。 有人有示例,以便我可以尝试了解它们的工作原理吗?

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

(?>) - atomic group

【问题讨论】:

标签: regex lookaround


【解决方案1】:

示例

给定字符串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)

往后看正面(?&lt;=)

在表达式 B 之前找到表达式 A:

(?<=B)A

看后面否定(?&lt;!)

找到表达式 B 不在前面的表达式 A:

(?<!B)A

原子团(?&gt;)

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

  • 应用于foots(?&gt;foo|foot)s 将匹配其第一个替代foo,然后由于s 未立即跟进而失败,并在禁用回溯时停止

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

  • (foo|foot)s 应用于foots 将:

    1. 匹配它的第一个替代方案foo,然后因为s 没有立即跟随foots 而失败,并返回到它的第二个替代方案;
    2. 匹配它的第二个备选foot,然后在s 紧跟在foots 之后成功,然后停止。

一些资源

在线测试人员

【讨论】:

  • “找到第二个小节”部分是什么意思?表达式/字符串中只有一个小节。谢谢
  • @ziggy 正在测试的字符串是“foobarbarfoo”。如您所见,字符串中有两个 foo 和两个 bar。
  • 有人能解释一下什么时候可能需要一个原子团吗?如果我只需要匹配第一个选项,我为什么要给出多个选项?
  • 关于原子团的更好解释this answer。有人可以在这里编辑以完成这个教学答案吗?
  • 请注意,当我最终完成一个需要严重正则表达式印章的项目时,这个答案是必不可少的。这是对环视的极好、简洁的解释。
【解决方案2】:

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

阅读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 确保字符串匹配其他一些规则。如果没有前瞻,它将匹配长度为 3 或 5 的字符串。

  • 负前瞻

语法:

(?!REGEX_1)REGEX_2

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

示例:

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

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

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

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

【讨论】:

  • 按照您的解释,似乎在 javascript 中不起作用,/(?=source)hello/.exec("source...hummhellosource") = null。你的解释正确吗?
  • @HelinWang 这个解释是正确的。您的正则表达式需要一个同时是 source 和 hello 的字符串!
  • @jddxf 需要详细说明吗?
  • @Amarghosh 我同意“他们检查正则表达式(朝向当前位置的右侧或左侧 - 基于前面或后面),在找到匹配项时成功或失败(基于是否正或负)并丢弃匹配的部分。”。所以前瞻应该检查当前位置右侧的正则表达式,并且正前瞻的语法应该是 x(?=y)
  • @Amarghosh 仅在 REGEX_2 出现 REGEX_1? 时才会匹配 (?=REGEX_1)REGEX_2
【解决方案3】:

快速环顾四周。
如何区分lookahead和lookbehind? 跟我一起来两分钟游览:

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

假设

    A  B  C #in a line

现在,我们问 B,你在哪里?
B 有两种解决方案来声明它的位置:

一,B前面有A,后面有C
二、B在C的前面(lookahead)和A的后面(lookhehind)。

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

【讨论】:

    猜你喜欢
    • 2015-09-13
    • 2021-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多