En fait le problème ne vient pas de la ponctuation, mais des hashtags ne comportant qu'un seul mot (cas auquel je n'avais pas pensé). Comme il faut obligatoirement enlever le # et qu'il n'est pas possible de faire un remplacement sans ajouter d'espace, on peut oublier preg_replace.
Donc mieux vaut utiliser preg_replace_callback pour isoler le tag et le traiter dans un deuxième temps:
$str = preg_replace_callback('~#(\pL+)~u', function ($m) { return preg_replace('~\B(?=\p{Lu})~u', ' ', $m[1]); }, $str);
Je viens de me rendre compte que \B avec le modificateur u ne fonctionne pas correctement avec PHP 7.3.0 alpha1 sur 3v4l.org. Donc au pire on peut écrire:
$str = preg_replace_callback('~#(\pL+)~u', function ($m) { return preg_replace('~(*UCP)\B(?=\p{Lu})~u', ' ', $m[1]); }, $str);
Partager