关于php:preg_match_all():如何使用regex正确查找所有出现的子字符串或分离的子字符串?

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

我的任务是在一个只有数字的字符串中查找所有连续的数字。不过,我并不是在寻找更好的regex来实现这一点,而是在寻找匹配子字符串的正确regex。

这就是我如何构建我的regex:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$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/

然后我这样做:

1
2
3
4
$literal = '234121678941251236544567812122345678';
$matches = [];
preg_match_all($myregex,$literal,$matches);
var_dump($matches);

结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
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, ...

然而,我尝试了用括号,+,和…并且没有找到找到所有匹配的正确regex(抱歉,仍然有点regex noob)。如何修改正则表达式?


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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$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).'/';

它的作用是使数字序列成为一个数组,然后按长度对它们排序,并首先将它们排序为最长的序列。最终结果是(匹配后)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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工作。+

希望它有帮助。

沙箱

and not go to the next chars after a match

我认为,如果你想在2345607中同时找到232342345,用regex是不可能的。但是,如果它匹配一个较长的序列,那么逻辑上它只能匹配一个较短的序列。所以你可以把右手边的数字剪掉,直到长度为2,然后得到匹配的结果。