【问题标题】:PHP Regexp (PCRE) - Find a set of all substrings 2PHP Regexp (PCRE) - 查找一组所有子字符串 2
【发布时间】:2011-03-11 18:22:33
【问题描述】:

例如有一个源字符串:

__aaXXccYYeeXX_ZZkkYYmmXX_ZZnnXXooYYuuXX_ZZvv..

我怎样才能找到所有:aaXX*YY*ZZ

__ aaXX cc YY eeXX_ ZZ kkYYmmXX_ZZnnXXooYYuuXX_ZZvv..

__ aaXX cc YY eeXX_ZZkkYYmmXX_ ZZ nnXXooYYuuXX_ZZvv..

__ aaXX cc YY eeXX_ZZkkYYmmXX_ZZnnXXooYYuuXX_ ZZ vv..

__ aaXX ccYYeeXX_ZZkk YY mmXX_ ZZ nnXXooYYuuXX_ZZvv..

__ aaXX ccYYeeXX_ZZkk YY mmXX_ZZnnXXooYYuuXX_ ZZ vv..

__ aaXX ccYYeeXX_ZZkkYYmmXX_ZZnnXXoo YY uuXX_ ZZ vv..

问题在于 PHP preg 不支持 (?

因此需要解决方案而不使用可变长度的后向断言。

谢谢!

【问题讨论】:

  • 我正在阅读的文档说 PHP 确实支持lookbehind。请发布您的代码。
  • @Cfreak - 它支持后视,但不支持可变长度。您可以在模式之前查找“foo”,但不能查找 [a-z]{2,3}; @Dmitrij,但为什么在这种情况下你需要向后看?

标签: php regex preg-match pcre


【解决方案1】:

此脚本有效:

<?php // test.php 20110311_1200
    $data = '__aaXXccYYeeXX_ZZkkYYmmXX_ZZnnXXooYYuuXX_ZZvv..';
    $all_matches = array();
    $yy_match = true; // Get past first for test condition.
    for ($yy_cnt = 1; $yy_match; ++$yy_cnt) {
        $yy_match = false; // Assume failure for this yy_cnt.
        $zz_match = true; // Get past first for test condition.
        for ($zz_cnt = 1; $zz_match; ++$zz_cnt) {
            $zz_match = false; // Assume failure for this zz_cnt.
            // Assemble new regex with new $yy_cnt and $zz_cnt.
            $re = "/ # Match all combinations of XX..YY..ZZ.
                (aaXX)                   # $1: Prefix X.
                (?:                      # Group to find YY[yy_cnt].
                  (?:(?!YY).)*           # Zero or more non-YY.
                  (YY)                   # $2: next YY.
                ){{$yy_cnt}}             # yy_cnt.
                (?:                      # Group to find ZZ[zz_cnt].
                  (?:(?!ZZ).)*           # Zero or more non-ZZ.
                  (ZZ)                   # $3 next ZZ.
                ){{$zz_cnt}}             # $zz_cnt.
                /x";
            if (preg_match($re, $data, $matches, PREG_OFFSET_CAPTURE)) {
                $zz_match = true;
                $yy_match = true;
                $all_matches[] = $matches;
                printf("Match found. \$yy_cnt = %d, \$zz_cnt = %d\n",
                    $yy_cnt, $zz_cnt);
            }
        }
    }
    print_r($all_matches);
?>

【讨论】:

    【解决方案2】:

    你需要循环。首先查找__aaXX,然后查找下一个YY,然后查找__aaXX,然后查找第二个YY 等。在正则表达式领域,这意味着您首先查找__aaXX(.*?YY){1},然后查找__aaXX(.*?YY){2}(您能看到一个循环吗?变量在那里?)等等,直到模式失败。当您寻找ZZs 时,第二部分也是如此。

    【讨论】:

    • 对不起,不明白。在正则表达式之外循环,你的意思是在 PHP 中?
    • @Dmitrij:是的,一个正则表达式不能一次性抓住它们。
    • bobbogo 是正确的。请参阅我对实现必要循环的测试脚本的回答。 (外环是YY,内环是ZZ)
    【解决方案3】:

    这个模式怎么样:# aaXX(.*) YY (.*) ZZ .*#

    从您的突出显示来看,您的结果应该是什么样子并不完全清楚...我添加了空格,因为您在突出显示中有它们,但不清楚您是否会将它们包含在您的源中...

    编辑

    我想我不明白你想得到什么,但另一件事是 preg_match_all,如果你的 YY ZZ 部分重复......像#_aaXX((.*?)YY(.*?)ZZ)+# 这样的东西。

    【讨论】:

      猜你喜欢
      • 2011-07-11
      • 2013-03-22
      • 1970-01-01
      • 1970-01-01
      • 2011-01-07
      • 2020-08-20
      • 2013-07-01
      • 2013-10-22
      • 1970-01-01
      相关资源
      最近更新 更多