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+
希望对您有所帮助。
and not go to the next chars after a match
我认为使用正则表达式是不可能的,例如,如果你的意思是你想在 2345607
中一次找到 23
234
2345
。但是,如果它匹配一个长序列,那么从逻辑上讲,它只能匹配一个较短的序列。所以你可以 trim 关闭右边的数字直到长度为 2 并获得匹配项。
我的任务是在只有数字的字符串中找到所有连续的数字。但是,我不是在寻找更好的正则表达式来执行此操作,而是在寻找匹配子字符串的正确正则表达式。
这就是我构建正则表达式的方式:
$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+
希望对您有所帮助。
and not go to the next chars after a match
我认为使用正则表达式是不可能的,例如,如果你的意思是你想在 2345607
中一次找到 23
234
2345
。但是,如果它匹配一个长序列,那么从逻辑上讲,它只能匹配一个较短的序列。所以你可以 trim 关闭右边的数字直到长度为 2 并获得匹配项。