RegEx для захвата групп между повторяющимися словами - PullRequest
2 голосов
/ 14 мая 2019

Ключевыми словами являются «* ИЛИ» или «* И».

Предположим, у меня есть строка ниже:

Это t3xt со специальными символами, такими как! #. * И это другой текст со специальными символами * И это повторяется * ИЛИ не повторить * ИЛИ иметь больше строк * И завершить эту строку.

Я хочу следующее

group1 "This is a t3xt with special characters like !#."  
group2 "*AND"  
group3 "and this is another text with special characters"  
group4 "*AND"  
group5 "this repeats"  
group6 "*OR"  
group7 "do not repeat"  
group8 "*OR"  
group9 "have more strings"  
group10 "*AND"  
group11 "finish with this string."  

Я пытался так:

(.+?)(\*AND\*OR)

но он получает только первую строку, тогда мне нужно продолжать повторять код, чтобы собрать остальные, но проблема в том, что есть строки, которые имеют только одну * И, или только одну * ИЛИ или десятки, то есть довольно случайно. И регулярное выражение ниже также не работает:

((.+?)(\*AND\*OR))+

Например:

Это t3xt со специальными символами, такими как! #. * И это другой текст со специальными символами

1 Ответ

2 голосов
/ 14 мая 2019

PHP имеет функцию preg_split для такого рода вещей. preg_split позволяет разбить строку по разделителю, который вы можете определить как шаблон регулярного выражения. Кроме того, он имеет аргумент, который позволяет вам включать совпавший разделитель в результаты сопоставления / разделения.

Таким образом, вместо написания регулярного выражения, соответствующего полному тексту, регулярное выражение предназначено для самого разделителя.

Пример:

$string = "This is a t3xt with special characters like !#. *AND and this is another text with special characters *AND this repeats *OR do not repeat *OR have more strings *AND finish with this string.";
$string = preg_split('~(\*(?:AND|OR))~',$string,0,PREG_SPLIT_DELIM_CAPTURE);
print_r($string);

Выход:

Array
(
    [0] => This is a t3xt with special characters like !#. 
    [1] => *AND
    [2] =>  and this is another text with special characters 
    [3] => *AND
    [4] =>  this repeats 
    [5] => *OR
    [6] =>  do not repeat 
    [7] => *OR
    [8] =>  have more strings 
    [9] => *AND
    [10] =>  finish with this string.
)

Но если вы действительно хотите придерживаться preg_match, вам вместо этого нужно будет использовать preg_match_all, что аналогично preg_match (что вы отметили в своем вопросе), за исключением того, что это делает глобальные / повторные совпадения.

Пример:

$string = "This is a t3xt with special characters like !#. *AND and this is another text with special characters *AND this repeats *OR do not repeat *OR have more strings *AND finish with this string.";
preg_match_all('~(?:(?:(?!\*(?:AND|OR)).)+)|(?:\*(?:AND|OR))~',$string,$matches);
print_r($matches);

Выход:

Array
(
    [0] => Array
        (
            [0] => This is a t3xt with special characters like !#. 
            [1] => *AND
            [2] =>  and this is another text with special characters 
            [3] => *AND
            [4] =>  this repeats 
            [5] => *OR
            [6] =>  do not repeat 
            [7] => *OR
            [8] =>  have more strings 
            [9] => *AND
            [10] =>  finish with this string.
        )

)

Во-первых, обратите внимание, что в отличие от preg_split, preg_match_allpreg_match) возвращают массив с множественным затемнением, а не одноцветный. Во-вторых, технически шаблон, который я использовал, можно немного упростить, но это будет стоить того, чтобы ссылаться на несколько массивов в возвращаемом множественном массиве (один массив для сопоставленного текста, а другой массив для сопоставленных разделителей) , что вам затем придется пройти через и альтернативную ссылку; IOW будет дополнительная очистка для получения окончательного единственного массива с обоими наборами совпадений, как указано выше.

Я показываю этот метод только потому, что вы технически задали его в своем вопросе, но я рекомендую использовать preg_split, так как он устраняет большую часть этих накладных расходов и почему он был создан в первую очередь (для лучшего решения сценариев как это).

...