PHP Regex(PCRE) - 查找所有子串的集合2

时间:2011-03-11 18:22:34

标签: php regex preg-match pcre

例如有一个源字符串:

__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_ZZnnXXooYYuXX_ 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不支持(?< = exp)lookbehind断言中的?+ *(可变长度)(仅允许使用固定长度{N})。

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

谢谢!

3 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分: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 :(得分:0)

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

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

修改

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