【问题标题】:PCRE regular expression overlapping matchesPCRE 正则表达式重叠匹配
【发布时间】:2016-02-17 13:34:57
【问题描述】:

我有以下字符串

001110000100001100001

还有这个表达方式

/[1]....[1]/g

这使得两个匹配

但我希望它也能匹配两者之间的模式,也就是说,重叠的 1

我完全不知道,这怎么行?而不是 0 它可以是任何字符

【问题讨论】:

  • /(pattern)(.*?)\1/ 使用它并获取第二个捕获的组值。无需往后看。
  • 如果您需要完全匹配,请尝试(?:.?(?<=1)....1)+

标签: php regex


【解决方案1】:

一个常见的技巧是在未锚定的正向前瞻中使用捕获技术。将此正则表达式与preg_match_all 一起使用:

(?=(1....1))

regex demo

values are in $matches[1]:

$re = "/(?=(1....1))/"; 
$str = "001110000100001100001"; 
preg_match_all($re, $str, $matches);
print_r($matches[1]);

lookahead reference:

Lookaround 实际上匹配字符,但随后放弃匹配,只返回结果:匹配或不匹配。这就是为什么它们被称为“断言”。它们不消耗字符串中的字符,而只是断言匹配是否可能。

如果您想将正则表达式的匹配项存储在前瞻中,您必须在前瞻中的正则表达式周围放置捕获括号,如下所示:(?=(regex)) .

【讨论】:

  • 非常感谢,我已经在积极前瞻的情况下玩 arround,但做得不对,这工作完美且解释清楚
  • 这是天才。我用正则表达式见过的最聪明的事情之一。谢谢!为我节省了很多时间。
【解决方案2】:

您也可以在lookbehind 中使用\K 功能(指返回结果的开始位置)来实现:

(?<=\K1)....1

demo

这样,您不需要创建捕获组,并且由于所有字符都被消耗(除了后面的第一个字符),正则表达式引擎不必为接下来的五个位置重试模式成功后。

$str = '001110000100001100001';

preg_match_all('~ (?<= \K 1 ) .... 1 ~x', $str, $matches);

print_r($matches[0]);

code

请注意,如果您确定第二个字符始终为零,则使用0(?&lt;=\K10)...1 会更高效,因为该模式以文字字符开头,并且 pcre 能够通过快速搜索主题字符串中的可能位置来优化它.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-10
    • 2010-09-24
    • 1970-01-01
    相关资源
    最近更新 更多