Expressions régulières : mettre les mots en majuscule dans un texte, en gras

Petit nouveau ! | 7 Messages

07 nov. 2017, 02:48

Bonjour,

J'ai des textes pour lesquels j'aimerai mettre automatiquement les mots qui sont en majuscule, en gras.
Par exemple si on trouve le mot "BONJOUR", cela sera transformé en "<strong>BONJOUR</strong>".
Cependant je n'arrive pas à créer d'expression régulière en PHP pour faire ça... J'ai besoin de vous ! Merci.

Voici un exemple de texte pour s'entraîner :

---
M. Cui s'exprimait lors d'un point de presse organisé à l'ambassade chinoise à Washington.
UNE OPPORTUNITÉ HISTORIQUE
M. Trump devrait se rendre en Chine le mois prochain dans le cadre de sa tournée en Asie, qui l'amènera également au Japon, en Corée du Sud, au Vietnam et aux Philippines.
"UNE VISITE D'ÉTAT PLUS"
M. Cui a indiqué que la Chine serait ravie de fournir une expérience de "visite d'Etat plus" au président Trump et à sa famille.
---

Un grand MERCI pour votre aide !!!

Eléphant du PHP | 63 Messages

07 nov. 2017, 18:10

Code : Tout sélectionner

$texte = <<<__texte__ M. Cui s'exprimait lors d'un point de presse organisé à l'ambassade chinoise à Washington. UNE OPPORTUNITÉ HISTORIQUE M. Trump devrait se rendre en Chine le mois prochain dans le cadre de sa tournée en Asie, qui l'amènera également au Japon, en Corée du Sud, au Vietnam et aux Philippines. "UNE VISITE D'ÉTAT PLUS" M. Cui a indiqué que la Chine serait ravie de fournir une expérience de "visite d'Etat plus" au président Trump et à sa famille. __texte__; // \p indique qu'on utilisera une propriété // {Lu} indique qu'on s'intéresse aux lettres (letter) majuscules (uppercase) // + pour prendre toute séquence d'au moins 1 lettre majuscule ou plus... // \b est une assertion pour détecter la frontière de mot, donc tout le mot doit-être en majuscule // car la séquence de lettres majuscule doit-être encadrée par des frontières de mot $regex = '#\b\p{Lu}+\b#u'; // enlever le u après le # si la chaine n'est pas en UTF-8 echo preg_replace($regex, '<strong>$0</strong>', $texte); // $0 réfère à la capture globale // remplacer le + par {2,} indiquerait que la séquence devrait avoir au moins 2 lettres majuscule // donc le M dans M. trump ne sera pas en gras car il faut un mot en majuscule s'au moins 2 lettres ou plus // enlever le u après le # si la chaine n'est pas en UTF-8 echo preg_replace('#\b\p{Lu}{2,}\b#u', '<strong>$0</strong>', $texte);

Petit nouveau ! | 7 Messages

08 nov. 2017, 03:46

Bonjour,

Ouah ! Merci pour cette réponse détaillée ! C'est très pédagogique et instructif !

Par contre j'ai un problème avec cette solution : s'il y a un apostrophe, cela ne marchera pas correctement car l'apostrophe n'est pas considéré comme une lettre. comment faire pour ajouter le ' par exemple (ex: TEST AVEC L'APOSTROPHE) et éventuellement d'autres caractères ?

MERCIIII !

Eléphant du PHP | 63 Messages

08 nov. 2017, 10:33

Bonjour,

On peut faire sa propre classe de caractères avec les crochets [] donc [\p{Lu}\'] voudrait dire d'inclure les lettres majuscules et l'apostrophe que j'ai échappé pour éviter un possible conflit avec PHP. Par contre, en encadrant avec des \b on pourrait détecter une frontière de mot avec une lettre minuscule car la classe de caractère inclue autre chose que des majuscules.

Code : Tout sélectionner

echo htmlspecialchars(preg_replace('#\b[\p{Lu}\']{2,}\b#u', '<strong>$0</strong>', "D'ÉTAT s'MAIS's")); // affichera <strong>D'ÉTAT</strong> s<strong>'MAIS'</strong>s // car les frontières seraient détectées entre les s minuscules et les apostrophes
Si ce n'est pas bon j'irais probablement vers un groupe facultatif avec * après le premier \b

Code : Tout sélectionner

$regex = '#\b(\p{Lu}+[\' ])*\p{Lu}{2,}\b#u'; // j'ai ajouté un espace dans la classe de caractères echo htmlspecialchars(preg_replace($regex, '<strong>$0</strong>', "D'ÉTAT s'MAIS's MOTS ENSEMBLES car AJOUT De l'ESPACE")); // affichera <strong>D'ÉTAT</strong> s'<strong>MAIS</strong>'s <strong>MOTS ENSEMBLES</strong> car <strong>AJOUT</strong> De l'<strong>ESPACE</strong>
Mais pour être exact il est peut-être préférable de construire ses propres frontières. Pour le \b de gauche (?<!\pL) pour dire n'est pas précédé d'une lettre et (?=\p{Lu}) pour dire doit-être suivi d'une lettre majuscule. Le \b de droite sera l'inverse (?<=\p{Lu}) doit-être précédé d'une lettre majuscule et (?!\pL) n'est pas suivi d'une lettre majuscule

Code : Tout sélectionner

$regex = '#(?<!\pL)(?=\p{Lu})[\p{Lu}\' ]{2,}(?<=\p{Lu})(?!\pL)#u'; // j'ai ajouté un espace dans la classe de caractères echo htmlspecialchars(preg_replace($regex, '<strong>$0</strong>', "D'ÉTAT s'MAIS's MOTS ENSEMBLES car AJOUT De l'ESPACE")); // affichera <strong>D'ÉTAT</strong> s'<strong>MAIS</strong>'s <strong>MOTS ENSEMBLES</strong> car <strong>AJOUT</strong> De l'<strong>ESPACE</strong>