Как я могу заменить все повторяющиеся знаки препинания на одиночные знаки препинания в PHP?

Есть ли эффективный способ заменить все повторяющиеся не буквенно-цифровые символы одиночными символами?

Этот вопрос заставляет быть явным в отношении знаков препинания:

PHP — Удаление повторяющихся знаков препинания?

Вот так:

$str = preg_replace('~[?!]{2,}~', '?', preg_replace('~([.,!?])(\\1+)~', '\\1', $str));

Можно ли добиться того же результата, но для ВСЕХ не буквенно-цифровых символов без явной ссылки на них по имени?

Вот вариант использования:

Hello...  how   are you!!??  I''m bored!!----!!!&&&&&^^^^%%%(()))((<<<<<

to

Hello. how are you!? I'm bored!-!&^%()(<

ОБНОВЛЕНИЕ

К сожалению, вышеизложенное слишком глубоко затрагивает один вариант использования: http://. Как можно сохранить двойные / для URL-адресов (или просто когда они следуют за :), но не разрешить регулярное повторение / или даже более 2 / после :. Вот один вариант использования:

My ////favorite//// site is http://///example.com!!!!!!!

становится:

My /favorite/ site is http://example.com!

person Ryan    schedule 14.01.2015    source источник


Ответы (1)


Вы можете использовать:

$str = preg_replace('~((?<!:)[^\p{L}\p{N}])\1+~u', '$1', $str);
//=> Hello. how are you!? I'm bored!-!&^%()(<

Демо RegEx

  • [^\p{L}\p{N}] — соответствует чему угодно, кроме буквенно-цифрового символа Юникода.
  • (?<!:) — Соответствует, только если перед ним не стоит :, чтобы учесть http://...
  • ([^\p{L}\p{N}]) - Захват выше в группе #1 для обратной ссылки
  • \1+ — Сопоставьте одну или несколько захваченных групп № 1, таким образом удостоверившись, что 2 или более одинаковых не буквенно-цифровых совпадают
  • Замените его на $1, т.е. захваченный не буквенно-цифровой символ
person anubhava    schedule 14.01.2015
comment
Потрясающая работа @anubhava. К сожалению, я слишком углубился в один вариант использования: http://. Можно ли исключить этот вариант использования (://), заменив при этом этот вариант использования: (hello////////there!)? См. пересмотренный вопрос выше для дальнейшего разъяснения. Еще раз спасибо, что завели меня так далеко. - person Ryan; 15.01.2015