【问题标题】:Overlapping matches with preg_match_all and pattern ending with repeated character重叠匹配与 preg_match_all 和以重复字符结尾的模式
【发布时间】:2017-04-04 02:05:46
【问题描述】:

我想做类似于问题preg_match_all how to get *all* combinations? Even overlapping ones 的事情,并找到给定模式的所有匹配项,即使它们重叠(例如,将字符串 ABABA 与模式 ABA 匹配应该返回 2 个匹配项,而不仅仅是第一个匹配项)。

但我有一个额外的限制:我的模式可以以重复说明符结尾。我们以+ 为例:这意味着模式/A+/ 和主题"AA" 应该返回3 个匹配项:

  • 从索引 0 开始匹配 "AA"
  • 从索引 1 开始匹配 "A"
  • 从索引 0 开始匹配 "A"

以下模式,基于对上述问题建议的解决方案,未能匹配所有 3 个结果:

  • 模式/(?=(A+))/ 仅查找前 2 个匹配项,但不查找最后一个匹配项
  • 模式/(?=(A+?))/ 仅查找最后 2 个匹配项,但不查找第一个匹配项

我目前唯一的解决方法是保留贪婪版本并尝试对每个匹配项应用模式减去其最后一个字符,重复此操作直到不再匹配,例如:

$all_matches = array ();
$pattern = 'A+';

preg_match_all("/(?=($pattern))/", "AA", $matches, PREG_SET_ORDER);

foreach ($matches as $match) {
    do {
        $all_matches[] = $match[1];
        $subject = substr($match[1], 0, -1);
    }
    while (preg_match("/^($pattern)/", $subject, $match));
}

有没有更好的解决方案可以使用 preg_match_all 或类似方法来实现这一点?

【问题讨论】:

  • 您想在一个索引处获得多个匹配项,而 1 次正则表达式匹配操作是不可能的。您实际上不想要纯正则表达式解决方案。您需要 1) 从您的字符串中找到所有子字符串的组合,并且 2) 只保留与您的模式完全匹配的子字符串。

标签: php regex


【解决方案1】:

您想在一个索引处获得多个匹配项,而 1 次正则表达式匹配操作是不可能的。你实际上需要

  • 从您的字符串中查找所有子字符串的组合并
  • 只保留与您的模式完全匹配的那些。

PHP demo

function find_substrings($r, $s) {
  $res = array();
  $cur = "";
  $r = '~^' . $r . '$~';
  for ($q = 0; $q < strlen($s); ++$q) {
    for ($w = $q; $w <= strlen($s); ++$w) {
        $cur = substr($s, $q, $w-$q);
        if (preg_match($r, $cur)) {
            array_push($res, $cur);
        }
    }
  }
  return $res;
}
print_r(find_substrings("ABA", "ABABA"));
// => Array ( [0] => ABA [1] => ABA )
print_r(find_substrings("A+", "AA"));
// => Array ( [0] => A [1] => AA [2] => A )

【讨论】:

  • 感谢您的回答和您对问题的清晰表述!似乎使用preg_match_all 和零长度前瞻技巧给函数一点提升,但结果是等价的。我会做更多的搜索,可能最终会使用它:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-02-18
  • 2022-07-21
  • 2013-07-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多