Как перехватить многострочное регулярное выражение между двумя тегами, которые находятся в разных шагах / массиве / месте - PullRequest
4 голосов
/ 24 мая 2019

Я использую TCPDF для создания сложных PDF-файлов, поэтому проблема заключается в том, что PDF-файл находится не на стандартной веб-странице

Я пытаюсь получить текст между двумя тегами, включая два тега: [#SCHANGE#]и [#ECHANGE#].

Я использую это регулярное выражение:

preg_match('/(?:\[#SCHANGE#\]((?:.*?\r?\n?)*)\[#ECHANGE#\])+/m', $textV, $StartEndChange);

$textV - это динамическое значение, которое пришло из цикла foreach, например:

foreach($text as $textV){

    //some code here..

}

и внутри могут быть разные ситуации, такие как:

$text = array (
    "0" => "[#SCHANGE#] same text [#ECHANGE#]" //This is okay, regex works in this case
) ;

Но это регулярное выражение не работает, когда в $text есть только один тег, тогда у меня такая ситуация:

$text = array (
    "0" => "[#SCHANGE#]same text",
    "1" => "some text",
    "2" => "some text",
    "3" => "some text",
    "4" => "some text",
    "5" => "some text",
    "6" => "some text",
    "7" => "some text [#ECHANGE#]"
) ;

Итак: как я могу получить текст между 2 тегами, включая два тега, если теги не находятся в одном и том же тексте?

Я не могу разбить массив, потому что весь текст внутри $text отформатирован иможет быть напечатан иначе, чем предыдущий или следующий

Ответы [ 3 ]

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

Я бы сначала взорвал массив, а затем поиска в строке:

$text = array (
    "[#SCHANGE#]same text",
    "some text",
    "some text",
    "some text",
    "some text",
    "some text",
    "some text",
    "some text [#ECHANGE#]",
    "blah blah",
    "[#SCHANGE#]other text[#ECHANGE#]"
) ;

$all_text = implode("\n", $text);
preg_match_all('/\[#SCHANGE#\][\s\S]+?\[#ECHANGE#\]/', $all_text, $matches);
print_r($matches);

Вывод:

Array
(
    [0] => Array
        (
            [0] => [#SCHANGE#]same text
some text
some text
some text
some text
some text
some text
some text [#ECHANGE#]
            [1] => [#SCHANGE#]other text[#ECHANGE#]
        )

)
1 голос
/ 27 мая 2019

Попробуйте это:

$re = '/(\[#SCHANGE#\](.+?)\[#ECHANGE#\])|(\[#SCHANGE#\](.+?$))|(^(.+?)\[#ECHANGE#\])/m';

$str = '[#SCHANGE#]same text
some text [#ECHANGE#]
[#SCHANGE#] same text [#ECHANGE#]';

preg_match_all($re, $str, $matches, PREG_SET_ORDER, 0);

// Print the entire match result
var_dump($matches);

RegEx

Если это выражение нежелательно, его можно изменить или изменить в regex101.com .

1 голос
/ 24 мая 2019

Ваше оригинальное выражение довольно близко.Мы могли бы просто захотеть взять (\[#SCHANGE#\]) и (\[#ECHANGE#\]) в качестве левой и правой границ, а затем собрать наш «некоторый текст», возможно, с выражением, похожим на:

(\[#SCHANGE#\])(.+?)(\[#ECHANGE#\])

Test

$re = '/(\[#SCHANGE#\])(.+?)(\[#ECHANGE#\])/m';
$str = '[#SCHANGE#] same text 1 [#ECHANGE#]
[#SCHANGE#] same text 2 [#ECHANGE#]
[#SCHANGE#] same text 3 [#ECHANGE#]
[#SCHANGE#] same text 4 [#ECHANGE#][#SCHANGE#] same text 5 [#ECHANGE#]';

preg_match_all($re, $str, $matches, PREG_SET_ORDER, 0);
$arr = array();
foreach ($matches as $key => $value) {$arr[$key] = $value[0];}
var_dump($arr);

Вывод

array(5) {
  [0]=>
  string(35) "[#SCHANGE#] same text 1 [#ECHANGE#]"
  [1]=>
  string(35) "[#SCHANGE#] same text 2 [#ECHANGE#]"
  [2]=>
  string(35) "[#SCHANGE#] same text 3 [#ECHANGE#]"
  [3]=>
  string(35) "[#SCHANGE#] same text 4 [#ECHANGE#]"
  [4]=>
  string(35) "[#SCHANGE#] same text 5 [#ECHANGE#]"
}

RegEx

Если это выражение нежелательно, его можно изменить или изменить в regex101.com .

enter image description here

RegEx Circuit

jex.im визуализирует регулярные выражения:

enter image description here

...