正则表达式找到顺序整数

时间:2011-01-04 18:53:41

标签: php regex overlapping-matches

我很难让我的正则表达式代码在PHP中正常工作。这是我的代码:

$array = array(); // Used to satisfy the 3rd argument requirment of preg_match_all.
$regex = '/(012|345|678|987|654|321|123|456|789|876|543|210|234|567|765|432)/';
$subject = '123456';
echo preg_match_all($regex, $subject, $array).'<br />';
print_r($array);

运行此代码时,它将输出:

2
Array
(
    [0] => Array
        (
            [0] => 123
            [1] => 456
        )
    [1] => Array
        (
            [0] => 123
            [1] => 456
        )
)

我能做什么才能匹配123,234,345和456?

提前致谢!

4 个答案:

答案 0 :(得分:2)

正则表达式不是这项工作的正确工具(它不会返回“子匹配”)。只需在循环中使用strpos

$subject = '123456';

$seqs = array('012', '345', '678', '987', '654', '321', '123', '456', '234');
foreach ($seqs as $seq) {
    if (strpos($subject, $seq) !== false) {
        // found
    }
}

答案 1 :(得分:1)

$regex = '/(?=(012|345|678|987|654|321|123|456|789|876|543|210|234|567|765|432))/';
$subject = '123456';
preg_match_all($regex, $subject, $array);
print_r($array[1]);

输出:

Array
(
    [0] => 123
    [1] => 234
    [2] => 345
    [3] => 456
)

您正在尝试检索主题字符串中彼此重叠的匹配项,这通常是不可能的。但是,在许多情况下,您可以通过将整个正则表达式包装在捕获组中来伪造它,然后将其包装在前瞻中。因为前瞻在匹配时不消耗任何字符,所以正则表达式引擎在每次成功匹配后手动向前移动一个位置,以避免卡在无限循环中。但捕获组仍然有效,因此您可以通常的方式检索捕获的文本。

请注意,我只打印了第一个捕获组($array[1])的内容。如果我打印了整个数组($array),它看起来像这样:

Array
(
    [0] => Array
    (
        [0] => 
        [1] => 
        [2] => 
        [3] => 
    )

    [1] => Array
    (
        [0] => 123
        [1] => 234
        [2] => 345
        [3] => 456
    )
)

<强> see it in action on ideone

答案 2 :(得分:0)

可以使用正则表达式完成。原始代码的问题在于,只要匹配发生,就会消耗该字符,并且正则表达式不会回溯。这是一种方法:

$array = array(); // Used to satisfy the 3rd argument requirment of preg_match_all.
$regex = '/012|345|678|987|654|321|123|456|789|876|543|210|234|567|765|432/';
$subject = '123456';

$tempSubject = $subject;
$finalAnswer = array();
do {
    $matched = preg_match($regex, $tempSubject, $array);
    $finalAnswer = array_merge($finalAnswer, $array);
    $tempSubject = substr($tempSubject, 1);
} while ($matched && (strlen($tempSubject >= 3)));
print_r($finalAnswer);

正如另一个答案中所建议的那样,正则表达式可能不是在这种情况下使用的正确工具,具体取决于您的更大目标。此外,上述代码可能不是使用正则表达式解决此问题的最有效方式(wrt memory或wrt performance)。这只是一个严格要求的满足要求的解决方案。

答案 3 :(得分:0)

是的,这是一个黑客,但你可以使用RegEx

<?php
$subject = '123456';

$rs = findmatches($subject);
echo '<pre>'.print_r($rs,true).'</pre><br />';


function findmatches($x) {
    $regex = '/(\d{3})/'; 

    // Loop through the subject string
    for($counter =  0; $counter <= strlen($x); $counter++) {
        $y = substr($x, $counter);
        if(preg_match_all($regex, $y, $array)) {
            $rs_array[$counter] = array_unique($array);
        }
    }

    // Parse results array
    foreach($rs_array as $tmp_arr) {
        $rs[] = $tmp_arr[0][0];
    }
    return $rs;
}
?>

返回:

Array
(
    [0] => 123
    [1] => 234
    [2] => 345
    [3] => 456
)

注意:这只适用于并发数字