Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Expression reguliere pour corriger la=?windows-1252?Q?_typographie_d'un_texte?

10 réponses
Avatar
Sebastien
Bonjour à tous,

Je cherche à corriger automatiquement la typographie d'un texte, saisi
par l'utilisateur dans un textarea HTML.
Cette correction est facultative, une case à cocher permet de l'activer
ou non et de plus il y a une prévisualisation avant soumission
définitive. Voici pour le décor.

-> essais de regexp en fin de post.

Objectifs :

Il s'agit de corrections pour les erreurs les plus fréquentes, comme
l'oubli de l'espace (insécable) avant les ponctuations doubles : ; ! ?
et à l'intérieur des guillemets français « et ».

Si l'espace est absent on ajoute un espace insécable, si un espace
normal est présent on le transforme en espace insécable.

Raffinement ultime (et complications à l'horizon), auquel je tiens
beaucoup, l'apostrophe droite est transformée en apostrophe «
typographiquement correcte » (').

Complication supplémentaire (voir point précédent), le texte peut
contenir du pseudo-code Wiki, avec en particulier '' (deux apostrophes
droites) entourant du texte devant être rendu en italique.

Pour finir, le tout est à destination d'une base de données MySQL, mais
cela n'a aucune incidence (si je ne m'abuse) car la chaîne sera insérée
avec mysql_real_escape_string(). On considère que la chaîne (reçue en
POST) est passée par stripslashes() si nécessaire avant tout traitement.


Les expressions :

<?php
function cleanup_typo($str)
{
$patterns[0] = '/([^\'].)\'([^\'].|0)/'; // Apostrophe droite non
précédée d'une autre apostrophe
$patterns[1] = '/([^ ]):/'; // Deux-points non précédé d'un espace
$patterns[2] = '/([^ ]);/'; // Point-virgule non précédé d'un espace
$patterns[3] = '/«([^ ])/'; // Guillemet ouvrant non suivi d'un espace
$patterns[4] = '/([^ ])»/'; // Guillemet fermant non précédé d'un espace
$patterns[5] = '/([^ ])!/'; // Point d'exclamation non précédé d'un espace
$patterns[6] = '/([^ ])\?/'; // Point d'interrogation non précédé d'un
espace
$patterns[7] = '/\.{3}/'; // Trois-points

$replacements[0] = '$1'$2';
$replacements[1] = '$1 :';
$replacements[2] = '$1 ;';
$replacements[3] = '« $1';
$replacements[4] = '$1 »';
$replacements[5] = '$1 !';
$replacements[6] = '$1 ?';
$replacements[7] = '--';

$str = preg_replace($patterns, $replacements, $str);

/* Ces 2 lignes sont issues de wiki2html : conversion en espaces
insécable des espaces existants */
$str = preg_replace('/[ ]+([:?!;»])/',' $1',$str);
$str = preg_replace('/(«)[ ]+/','$1 ',$str);

return $str;
}
?>

Si vous avez lu jusqu'ici sans tricher, bravo et merci.

Je suis intéressé par vos observations à tous les niveaux :
- problèmes liés aux risques de remplacer du texte qui ne devrait pas l'être
- erreurs dans les regexp (pourtant testée, mais peut-être pas sur tous
les cas)
- Possibilités d'optimisation
- Mauvaise interprêtation des règles de typographie française
- ...

Ceci n'est qu'un premier jet, je ne suis toujours pas un expert en
expressions régulières. Je n'ai fait que quelques tests e tje sens que
mes expressions sont pleines de trous...


Sébastien

10 réponses

Avatar
Sebastien
Bonjour à tous,

Je ne sais pas si mon idée vous paraît trop farfelue ou quoi, laissez
quand même vos impressions.

Quelques modifications :

Pour ne pas transformer "http:" en "http :"
j'ai ajouté ces lignes en fin de fonction :

<?php
$str = preg_replace('/(http|https|ftp|news|mailto) :/','$1:',$str);
$str = preg_replace('/(http|https|ftp|news|mailto) :/','$1:',$str);
?>

De plus j'ai oublié de préciser que dans les remplacements les espaces
insérés ou remplacés sont des espaces insécables directement saisis sous
forme de caractère, pour éviter que les esperluettes des appels &#160;,
&#xa0; ou &nbsp; ne soient à leur tour convertis en &amp; (donnant
respectivement &amp;#160;, &amp;#xa0; et &amp;nbsp;) par
htmlspecialchars() ou htmlentities().

Sébastien
Avatar
Florian Sinatra
*Sebastien* @ 26/03/2006 11:54 :

Note préliminaire : je suis une bille en ExpReg.

<?php
function cleanup_typo($str)
{
$patterns[0] = '/([^'].)'([^'].|0)/'; // Apostrophe droite non
précédée d'une autre apostrophe
$patterns[1] = '/([^ ]):/'; // Deux-points non précédé d'un espace
$patterns[2] = '/([^ ]);/'; // Point-virgule non précédé d'un espace
$patterns[3] = '/«([^ ])/'; // Guillemet ouvrant non suivi d'un espace
$patterns[4] = '/([^ ])»/'; // Guillemet fermant non précédé d'un espace
$patterns[5] = '/([^ ])!/'; // Point d'exclamation non précédé d'un espace
$patterns[6] = '/([^ ])?/'; // Point d'interrogation non précédé d'un
espace
$patterns[7] = '/.{3}/'; // Trois-points


A l'avenir, tu pourrais utiliser un autre délimiteur :
<http://expreg.com/expreg_article.php?art=apcre_delim>

$replacements[0] = '$1'$2';


Ca n'a aucune chance de fonctionner : tu dois avoir une erreur de
parsing. Echappe ton apostrophe entre $1 et $2.

$replacements[1] = '$1 :';
$replacements[2] = '$1 ;';
$replacements[3] = '« $1';
$replacements[4] = '$1 »';
$replacements[5] = '$1 !';
$replacements[6] = '$1 ?';
$replacements[7] = '--';


Pourquoi remplacer les trois points par deux tirets ?

$str = preg_replace($patterns, $replacements, $str);

/* Ces 2 lignes sont issues de wiki2html : conversion en espaces
insécable des espaces existants */
$str = preg_replace('/[ ]+([:?!;»])/',' $1',$str);
$str = preg_replace('/(«)[ ]+/','$1 ',$str);


Ces espaces n'ont rien d'insécable. Et tu ne pourras les insécabiliser
après, vu qu'il sera impossible de les différencier...

Avatar
Olivier Miakinen


$replacements[0] = '$1'$2';


Ca n'a aucune chance de fonctionner : tu dois avoir une erreur de
parsing. Echappe ton apostrophe entre $1 et $2.


Je suppose que c'est le gentil robot de modération qui a transformé son
apostrophe CP1252 en patte de mouche ASCII. ;-)

Cela dit, Sébastien, je te déconseille d'utiliser CP1252 pour ta page
web -- et ce d'autant plus si tu déclares ISO-8859-1.

Il vaudrait mieux écrire :
$replacements[0] = '$1&rsquo;$2';
ou bien :
$replacements[0] = '$1&#8217;$2';

À moins que ta page ne soit en UTF-8, auquel cas il n'y a pas de problème.

$replacements[7] = '--';


Pourquoi remplacer les trois points par deux tirets ?


Pas compris non plus. C'est encore le robot qui a corrigé le code
CP1252 ?

Tu peux écrire :
$replacements[7] = '&hellip;';

Mais personnellement j'ai horreur de ce caractère « trois points » et je
préfère garder « ... ».

/* Ces 2 lignes sont issues de wiki2html : conversion en espaces
insécable des espaces existants */
$str = preg_replace('/[ ]+([:?!;»])/',' $1',$str);
$str = preg_replace('/(«)[ ]+/','$1 ',$str);


Ces espaces n'ont rien d'insécable. Et tu ne pourras les insécabiliser
après, vu qu'il sera impossible de les différencier...


Alors là ce n'est pas à cause du robot, mais de vos nouvelleurs à
tous les deux. Sébastien utilise Thunderbird qui remplace les espaces
insécables par des espaces simples à l'envoi, et toi tu utilise aussi
Thunderbird qui les aurait remplacées aussi à la lecture si ce n'avait
pas été fait à l'envoi. Et avec mon Mozilla je ne peux pas non plus
distinguer les deux.

--
Olivier Miakinen
Troll du plus sage chez les conviviaux : le nouveau venu, avec
son clan, s'infiltre dans les groupes de nouvelles. (3 c.)


Avatar
Florian Sinatra
*Olivier Miakinen* @ 28/03/2006 19:03 :


$replacements[0] = '$1'$2';


Ca n'a aucune chance de fonctionner : tu dois avoir une erreur de
parsing. Echappe ton apostrophe entre $1 et $2.



Je suppose que c'est le gentil robot de modération qui a transformé son
apostrophe CP1252 en patte de mouche ASCII. ;-)


Cette fameuse apostrophe, elle est censée ressembler à quoi ? C'est que
dans CP1252 ? Elle s'obtient par le clavier ?

Alors là ce n'est pas à cause du robot, mais de vos nouvelleurs à
tous les deux. Sébastien utilise Thunderbird qui remplace les espaces
insécables par des espaces simples à l'envoi, et toi tu utilise aussi
Thunderbird qui les aurait remplacées aussi à la lecture si ce n'avait
pas été fait à l'envoi. Et avec mon Mozilla je ne peux pas non plus
distinguer les deux.


Idem, comment l'obtenir ? Quel est son code ?



Avatar
Sebastien

Merci Olivier d'avoir répondu, fort justement, à ma place. Je vais donc
confirmer et préciser également pour Florian. Merci pour vos réponses.

$replacements[0] = '$1'$2';


Ca n'a aucune chance de fonctionner : tu dois avoir une erreur de
parsing. Echappe ton apostrophe entre $1 et $2.


Je suppose que c'est le gentil robot de modération qui a transformé son
apostrophe CP1252 en patte de mouche ASCII. ;-)


Tout à fait. J'ai fait l'erreur de ne pes prévor des explications à ce
sujet.

Cela dit, Sébastien, je te déconseille d'utiliser CP1252 pour ta page
web -- et ce d'autant plus si tu déclares ISO-8859-1.


Jamais je n'utiliserais CP1252 sur le web, sois-en assuré !

À moins que ta page ne soit en UTF-8, auquel cas il n'y a pas de problème.


C'est effectivement le cas et je précise donc que tout est sensé être en
utf-8, même les données à corriger.

$replacements[7] = '--';


Pourquoi remplacer les trois points par deux tirets ?


Pas compris non plus. C'est encore le robot qui a corrigé le code
CP1252 ?


Encore exact,

Mais personnellement j'ai horreur de ce caractère « trois points » et je
préfère garder « ... ».


Je préfère pour ma part le trois-points sous forme de caractère.
Question de goût, mais c'est facilement adaptable par chacun.

/* Ces 2 lignes sont issues de wiki2html : conversion en espaces
insécable des espaces existants */
$str = preg_replace('/[ ]+([:?!;»])/',' $1',$str);
$str = preg_replace('/(«)[ ]+/','$1 ',$str);


Ces espaces n'ont rien d'insécable. Et tu ne pourras les insécabiliser
après, vu qu'il sera impossible de les différencier...


Alors là ce n'est pas à cause du robot, mais de vos nouvelleurs à
tous les deux. Sébastien utilise Thunderbird qui remplace les espaces
insécables par des espaces simples à l'envoi, et toi tu utilise aussi
Thunderbird qui les aurait remplacées aussi à la lecture si ce n'avait
pas été fait à l'envoi. Et avec mon Mozilla je ne peux pas non plus
distinguer les deux.


Je pense que ça vient de plus loin : Windows transforme apparemment les
espaces insécables en espaces normaux au moment de la copie (Ctrl+V).
Car il s'agit bien dans mon code d'un espace insécable sous forme de
caractère, que'on ne peut donc pas distinguer même en tant que tel. La
raison est celle que j'ai déjà donnée : le risque de voir les
esperluettes d'un appel de caractère transformée en &amp;.

Sur ce point si vous avez des idées...

Sébastien



Avatar
Olivier Miakinen

Alors là ce n'est pas à cause du robot, mais de vos nouvelleurs à
tous les deux. Sébastien utilise Thunderbird qui remplace les espaces
insécables par des espaces simples à l'envoi, et toi tu utilise aussi
Thunderbird qui les aurait remplacées aussi à la lecture si ce n'avait
pas été fait à l'envoi. Et avec mon Mozilla je ne peux pas non plus
distinguer les deux.


Je pense que ça vient de plus loin : Windows transforme apparemment les
espaces insécables en espaces normaux au moment de la copie (Ctrl+V).


Non, je viens de refaire quelques tests qui prouvent que ce n'est pas
Windows mais certaines applications.

D'après mes tests, les applications qui perdent l'espace insécable
incluent Thunderbird, Mozilla, mais aussi Wordpad. Inversement, les
applications qui ne perdent pas l'insécable incluent Notepad, et vim
sous cygwin.

Car il s'agit bien dans mon code d'un espace insécable sous forme de
caractère, que'on ne peut donc pas distinguer même en tant que tel. La
raison est celle que j'ai déjà donnée : le risque de voir les
esperluettes d'un appel de caractère transformée en &amp;.


Et si tu transformais les « & » en « &amp; » *avant* de faire les autres
transformations ? Ainsi tu ne perdrais aucune information.


Avatar
Olivier Miakinen

Je suppose que c'est le gentil robot de modération qui a transformé son
apostrophe CP1252 en patte de mouche ASCII. ;-)


Cette fameuse apostrophe, elle est censée ressembler à quoi ?


Je ne peux pas l'inclure dans un article sur usenet-fr puisqu'elle n'est
ni dans ISO-8859-1 ni dans ISO-8859-15.

Mais tu peux la voir ici : <http://www.miakinen.net/vrac/charsets/>,
onglet CP1252, caractère 92 en hexa (en dessous du r et juste au dessus
du ¢ barré). Comparer avec l'apostrophe droite en 27 hexa.

C'est que dans CP1252 ?


Elle est bien sûr aussi dans toute représentation complète d'Unicode,
par exemple UTF-8. Mais elle n'est dans aucune des 5 autres tables 8bits
de ma page déjà citée.

Elle s'obtient par le clavier ?


Oui, par exemple avec Alt+0146 si tu as un Windows en CP1252. Mais
aussi par AltGr+K si tu as installé le clavier de Denis Liégeois :
<http://home.pro.tiscali.be/~fbou2235/kbdfrac.htm>.

[ espace insécable ]


Idem, comment l'obtenir ? Quel est son code ?


Alt+0160 (code CP1252)
Alt+255 (code CP850)
AltGr+< (clavier Liégeois)


Avatar
Florian Sinatra
Merci pour tes précisions !
Avatar
Laurent
pour info :
http://polenord.blogspot.com/2006/03/une-fonction-pour-remplacer-les.html

remplace les guillemets simples et doubles de word, ainsi que le symbole
euro et les points de suspension word... On peut évidemment agrandir la
liste !
Avatar
Sebastien
Note : je continuerai à publier ici les avancées de cette fonction, mais
je n'ai pas le temps dans l'immédiat.
remplace les guillemets simples et doubles de word, ainsi que le symbole
euro et les points de suspension word... On peut évidemment agrandir la
liste !


Je cherche à faire exactement le contraire : transformer une typographie
française défectueuse issue d'une saisie clavier en une typographie
françaie correcte. Les guillemets français sous Word sont parfaitement
corrects. De même le symbole Euro, les trois points, etc. sont
parfaitement acceptables et même, dans ce cas, désirés.

Sébastien