У меня есть 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);
}
Как говорится в комментариях, регулярное выражение очень неэффективно и, вероятно, является причиной — вы можете сделать все это с помощью одного регулярного выражения:
\[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, возможно, будет лучше.
Других решений пока нет …