Это действительно неэффективная проблема для решения с помощью регулярных выражений, особенно если повторяющееся выражение произвольно велико. На практике этого достаточно, чтобы ограничить длину повторяющегося выражения примерно 3–5, и это должно быть намного проще.
Что-то вроде
$title = preg_replace('/(\W{1,5})(?=\1+)/', '', $title);
должно работать.
Некоторые предварительные испытания показывают, что
$title = 'Buy my product !!!!!!!!!!!!!!!!!!!!!!!! Buy my product !? !? !? !? !? !? Buy my product !!!!!!!!!.......!!!!!!!! Buy my product <-----------';
$title = preg_replace('/(\W{1,5})(?=\1{2,})/', '', $title);
echo $title;
выдаст
Buy my product !! Buy my product !? !? Buy my product !!..!! Buy my product <--
Похоже, что вы прошли все ваши тесты.
Re: Гордон
Ваша строка:
¸·´`·¸·´`·¸·´`·¸ Human ·-> creativity << is endless !¡!¡! ☻☺
не повторяет ничего, кроме первой части более двух раз. Кажется, требуется:
$title = preg_replace('/(\W{1,9})(?=\1{2,})/', '', $title);
, прежде чем оно упрощается до
¸·´`·¸·´`·¸ Human ·-> creativity << is endless !¡!¡! ☻☺
(что означает, что preg_replace
не поддерживает Unicode - да ладно)
Вы также можете настроить его так, чтобы он повторялся только один раз:
$title = preg_replace('/(\W{1,9})(?=\1+)/', '', $title);
, в этом случае оно становится:
¸·´`·¸ Human ·-> creativity < is endless !¡! ☻☺
Если вы считаете, что можно создать множество «ASCII-изображений», даже если требуется повторить их менее двух раз, ну, это выходит за рамки этого вопроса. Чтобы свести к минимуму искусство ASCII, я бы порекомендовал просто использовать что-то вроде:
preg_replace('/(\W{5})\W+/', '$1', $title);
(т. Е. Просто укажите количество не буквенно-цифровых символов, которые могут отображаться в строке. Обратите внимание, что это необходимо настроить для совместимости с языками с нелатинскими алфавитами, такими как русский).