PHP: preg_match_all () - как правильно найти все вхождения разделенных ИЛИ подстрок с регулярным выражением? - PullRequest
0 голосов
/ 05 октября 2018

Моя задача - найти все последовательные числа в строке только чисел.Однако я ищу не лучшее регулярное выражение для этого, а правильное регулярное выражение соответствующих подстрок.

Вот как я строю свое регулярное выражение:

$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, ...

Однако я пробовал различные варианты в скобках, +, ... и не нашел правильного регулярного выражения, чтобы найти все совпадений (извините, все еще что-то вроде регулярного выражения noob).Как мне изменить регулярное выражение?

1 Ответ

0 голосов
/ 05 октября 2018

Порядок регулярных выражений важен.Я не уверен, что если это полностью решит проблему, то метод такого подхода может быть в корне ошибочным, но вы можете попробовать это:

$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 +

Надеюсь, это поможет.

Песочница

и не переходить к следующим символам после матча

Я не думаю, что это возможно с регулярным выражением, если вы хотите найти 23 234 2345 все сразу, например, 2345607.Однако, если он соответствует длинной последовательности, то логично предположить, что он должен соответствовать более короткой.Таким образом, вы можете просто обрезать номер правой руки, пока длина не станет 2 и получить совпадения.

...