PHP: preg_match_all() - 如何使用正则表达式正确查找所有出现的 OR 分隔子字符串?

PHP: preg_match_all() - how to find all occurrences of OR seperated substrings with a regex correctly?

我的任务是在只有数字的字符串中找到所有连续的数字。但是,我不是在寻找更好的正则表达式来执行此操作,而是在寻找匹配子字符串的正确正则表达式。

这就是我构建正则表达式的方式:

$regex = "";

for($i=0;$i<10;$i++) {
    $str = "";
    for($a=0;$a<10;$a++) {
        if($a > $i) {
            $str .= $a;
            if(strlen($str)>1) {
              $regex .= "|".$str."";
            }
        }
    }
}

$myregex = "/".ltrim($regex,"|")."/";
echo $myregex;

结果:

/12|123|1234|12345|123456|1234567|12345678|123456789|23|234|2345|23456|234567|2345678|23456789|34|345|3456|34567|345678|3456789|45|456|4567|45678|456789|56|567|5678|56789|67|678|6789|78|789|89/

然后我做:

$literal = '234121678941251236544567812122345678';
$matches = [];
preg_match_all($myregex,$literal,$matches);
var_dump($matches);

结果:

array(1) {
  [0]=>
  array(13) {
    [0]=>
    string(2) "23"
    [1]=>
    string(2) "12"
    [2]=>
    string(2) "67"
    [3]=>
    string(2) "89"
    [4]=>
    string(2) "12"
    [5]=>
    string(2) "12"
    [6]=>
    string(2) "45"
    [7]=>
    string(2) "67"
    [8]=>
    string(2) "12"
    [9]=>
    string(2) "12"
    [10]=>
    string(2) "23"
    [11]=>
    string(2) "45"
    [12]=>
    string(2) "67"
  }
}

但是我想找到所有出现的子字符串(而不是在匹配后转到下一个字符)——比如:

23,234,34,12,67,678,6789,78,789,89,12, ...

但是我尝试了不同的方括号、+、...的变体,但没有找出正确的正则表达式来找到 all 匹配项(抱歉,仍然有点正则表达式菜鸟).我必须如何修改正则表达式?

正则表达式的顺序很重要。我不确定这是否能完全解决问题,这样做的方法可能存在根本性缺陷,但您可以试试这个:

$regex = [];

for($i=0;$i<10;$i++) {
    $str = "";
    for($a=0;$a<10;$a++) {
        if($a > $i) {
            $str .= $a;
            if(strlen($str)>1) {
              $regex[] = $str;
            }
        }
    }
}

usort($regex, function($a,$b){
    return strlen($b) <=> strlen($a);
});

$myregex = '/'.implode('|', $regex).'/';

它的作用是把数字序列做成一个数组,然后按长度排序,最长的序列排在最前面。最终结果是这样的(匹配后)

array(1) {
  [0]=>
  array(9) {
    [0]=>
    string(3) "234"
    [1]=>
    string(2) "12"
    [2]=>
    string(4) "6789"
    [3]=>
    string(2) "12"
    [4]=>
    string(3) "123"
    [5]=>
    string(5) "45678"
    [6]=>
    string(2) "12"
    [7]=>
    string(2) "12"
    [8]=>
    string(7) "2345678"
  }
}

另请注意飞船运算符 <=> 仅适用于 PHP7+

希望对您有所帮助。

Sandbox

and not go to the next chars after a match

我认为使用正则表达式是不可能的,例如,如果你的意思是你想在 2345607 中一次找到 23 234 2345。但是,如果它匹配一个长序列,那么从逻辑上讲,它只能匹配一个较短的序列。所以你可以 trim 关闭右边的数字直到长度为 2 并获得匹配项。