Regex тайм-аут в PHP 7?

У меня есть 2 регулярных выражения ниже, которое работает в php 5.6, но не будет работать в php 7.x, если символ + пробел> 1035 иш. Пример: [спойлер] 1035 символов char + ws [/ spoiler]. Я использовал сайт, http://regexr.com/, проверить регулярное выражение с http://pastebin.com/5bWzhNvy и, кажется, работает нормально.

От PHP 7 регулярное выражение не работает так же, как в 5, я вижу, что проблема может быть с тайм-аутом регулярных выражений? Но вот код, если я не ошибаюсь.

// [spoiler]Text[/spoiler]
preg_match_all('/\[spoiler\]\s*((\s|.)+?)\s*\[\/spoiler\]/', $s, $matches, PREG_SET_ORDER);
foreach ($matches as $match) {
$id = substr(md5($match[1]), 0, 10) . mt_rand(0, 10000);
$s  = str_replace($match[0],
'<a href="javascript:klappe_function(\'' . $id . '\')" style="color: #aaa" title="Open Spoiler"><img src="https://web-answers.ru/wp-content/uploads/2019/02/plus.png" id="pic' . $id . '" class="spoiler" alt="spoiler" /></a><div id="k' . $id . '" style="display: none;">' . $match[1] . '</div><br />',
$s);
}

// [spoiler=Heading]Text[/spoiler]
preg_match_all('/\[spoiler=(.+?)\]\s*((\s|.)+?)\s*\[\/spoiler\]/', $s, $matches, PREG_SET_ORDER);
foreach ($matches as $match) {
$id = substr(md5($match[2]), 0, 10). mt_rand(0, 10000);
$s  = str_replace($match[0],
'<a href="javascript:klappe_function(\'' . $id . '\')" style="color: #aaa" title="Open ' . myhtmlentities($match[1], ENT_QUOTES)  . '"><img src="https://web-answers.ru/wp-content/uploads/2019/02/plus.png" id="pic' . $id . '" class="spoiler" alt="spoiler" /> <b>' . $match[1] . '</b></a><div id="k' . $id . '" style="display: none;">' . $match[2] . '</div><br />',
$s);
}

1

Решение

Как говорится в комментариях, регулярное выражение очень неэффективно и, вероятно, является причиной — вы можете сделать все это с помощью одного регулярного выражения:

\[spoiler(:?\=([^\]]+))?\]((:?[^\[]+|\[(?!=\/spoiler\]))+)\[\/spoiler\]

  • \[spoiler Матчи [spoiler
  • (:? запускает группу без захвата (не в $ match)
    • \= Матчи =
    • ( начать первую группу захвата
    • [^\]]+ соответствует чему-либо, кроме ] обуглить один или несколько раз.
    • ) закрыть первую группу захвата
  • )? закрывает группу и делает ее необязательной
  • ( начать вторую группу соответствия
    • (:? запускает группу без захвата (не в $ match)
      • [^\[]+ соответствует чему-либо, кроме [ обуглить один или несколько раз
      • | или же
      • \[(?!=\/spoiler\] один [ символ, пока за ним не следуют /spoiler]
    • )+ повторить группу один или несколько раз
  • ) закрыть вторую подходящую группу
  • \[\/spoiler\] Матчи [/spoiler]

Это учитывает оба сценария (просто проверьте, пустой ли $ match [1], чтобы сказать, какой), но он не пробует и не удаляет пробелы, вы можете легко сделать это в php после использования trim($match[1],"\r\n\t ")

Две ключевые вещи здесь:

Соответствие тексту заголовка

[^\]]+ соответствует чему-либо, кроме [ обуглить один или несколько раз.

Это намного быстрее, чем поиск любого символа — который вызвал бы «возврат», см .: http://www.regular-expressions.info/catastrophic.html

соответствие содержимого спойлера

  • (:? запускает группу без захвата (не в $ match)
    • [^\[]+ соответствует чему-либо, кроме [ обуглить один или несколько раз
    • | или же
    • \[(?!=\/spoiler\] один [ символ, пока за ним не следуют /spoiler]
  • )+ повторить группу один или несколько раз

Это позволяет [ символы внутри вашего текста спойлера, но опять же, не вызывая возврата. Это делается путем поиска серии не [ символы или же один [ символ, если за ним сразу не следует /spoiler] — это «негативный взгляд», см .: http://www.regular-expressions.info/lookaround.html

Несмотря на это, regex, вероятно, не лучший инструмент для работы, если вы хотите сделать это эффективно, токенайзер или, возможно, preg_split, возможно, будет лучше.

-1

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector