Discussion:
unicode (?), regexp, SQL... le bordel
(trop ancien pour répondre)
Olivier Masson
2009-10-16 13:40:29 UTC
Permalink
Bonjour,

J'ai du mal à comprendre et surtout à résoudre un problème tout bête.

Je cherche à parser un texte à la recherche d'expressions présentes dans
une base. Ce que font les tonnes des trucs à la autolink.

Mais, si tout va bien dans mes tests hors SQL, si tout va bien sur la
pluparts des mots et expressions, ça foire avec les quotes.

Ceci place des % entre les expressions ($exp) trouvées dans la base MySQL :
preg_replace ( "#(\W)(" . preg_quote ( $exp ) . ")(\W)#Ui" ,
'${1}%${2}%${3}' , $texte , $max );

Si, au sein du script php, je cherche "aujourd'hui", ça ne fonctionne pas.
Normal, le problème est que le texte original transforme les ' en ' (je
ne le contrôle pas).
Donc, toujours au sein du script, je cherche "aujourd'hui" et là, ça
fonctionne.

Par contre, quand j'utilise la sortie MySQL, ça ne fonctionne plus. J'ai
beau faire un str_replace("'","'",$texte) ou un
str_replace("'","'",$exp), ça ne fonctionne pas du moment que $exp vient
de la base de données.

Pourtant, quand je fais un echo du $exp sorti de la base et que je fais
un copier/coller dans le script, ça fonctionne.

Tout est censé être en utf-8 et j'ai même insisté avec un
set_charset('utf8') pour la connexion MySQL.

Alors bon, j'en ai marre :(
Olivier Miakinen
2009-10-16 13:46:54 UTC
Permalink
[Publication en UTF-8]

Bonjour,
[...] je cherche "aujourd'hui", ça ne fonctionne pas.
[...] transforme les ' en ' [...]
[...] je cherche "aujourd'hui" et là, ça fonctionne.
[...] str_replace("'","'",$texte) [...]
Tu devrais republier ton article en UTF-8 plutôt qu'en Windows-1252, il
y a moins de risques que les ’ se transforment en ', rendant ta question
incompréhensible.

Cordialement,
--
Olivier Miakinen
Olivier Masson
2009-10-16 14:34:56 UTC
Permalink
Post by Olivier Miakinen
Tu devrais republier ton article en UTF-8 plutôt qu'en Windows-1252, il
y a moins de risques que les ’ se transforment en ', rendant ta question
incompréhensible.
Cordialement,
/ Merci Olivier, je pensais que Tb faisait ça comme un grand (d'ailleurs
c'est iso-8859-1 qui est choisi dans ma conf, pas windows-1252 : pas
bien Tb !)
Je reprends donc : /

Bonjour,

J'ai du mal à comprendre et surtout à résoudre un problème tout bête.

Je cherche à parser un texte à la recherche d'expressions présentes dans
une base. Ce que font les tonnes des trucs à la autolink.

Mais, si tout va bien dans mes tests hors SQL, si tout va bien sur la
pluparts des mots et expressions, ça foire avec les quotes.

Ceci place des % entre les expressions ($exp) trouvées dans la base MySQL :
preg_replace ( "#(\W)(" . preg_quote ( $exp ) . ")(\W)#Ui" ,
'${1}%${2}%${3}' , $texte , $max );

Si, au sein du script php, je cherche "aujourd'hui", ça ne fonctionne pas.
Normal, le problème est que le texte original transforme les ' en ’ (je
ne le contrôle pas).
Donc, toujours au sein du script, je cherche "aujourd’hui" et là, ça
fonctionne.

Par contre, quand j'utilise la sortie MySQL, ça ne fonctionne plus. J'ai
beau faire un str_replace("’","'",$texte) ou un
str_replace("'","’",$exp), ça ne fonctionne pas du moment que $exp vient
de la base de données.

Pourtant, quand je fais un echo du $exp sorti de la base et que je fais
un copier/coller dans le script, ça fonctionne.

Tout est censé être en utf-8 et j'ai même insisté avec un
set_charset('utf8') pour la connexion MySQL (j'ai aussi forcé avec un
iconv sans résultat).


Alors bon, j'en ai + que marre :(


PS : pourquoi les mb_ utilisent les regex POSIX (y'a pas de mb_ereg)
alors qu'elles sont dépréciées ?
Olivier Miakinen
2009-10-16 14:57:57 UTC
Permalink
Le 16/10/2009 16:34, Olivier Masson a écrit :
<HS>
Post by Olivier Masson
Post by Olivier Miakinen
Tu devrais republier ton article en UTF-8 plutôt qu'en Windows-1252, il
y a moins de risques que les ’ se transforment en ', rendant ta question
incompréhensible.
Cordialement,
/ Merci Olivier, je pensais que Tb faisait ça comme un grand (d'ailleurs
c'est iso-8859-1 qui est choisi dans ma conf, pas windows-1252 : pas
bien Tb !)
Je pense que c'est intl.fallbackCharsetList.ISO-8859-1 qui vaut
windows-1252 par défaut et qu'il faut changer pour autre chose.

Tu peux y mettre UTF-8, mais personnellement j'y ai mis ISO-8859-15 et
ça marche très bien : Thunderbird choisit tout seul entre ISO-8859-1 et
ISO-8859-15 quand il le peut, et sinon il me demande de confirmer le
passage à UTF-8.
</HS>
Post by Olivier Masson
Je reprends donc : /
[...]
preg_replace ( "#(\W)(" . preg_quote ( $exp ) . ")(\W)#Ui" ,
'${1}%${2}%${3}' , $texte , $max );
Tiens, j'ai oublié de te signaler un truc dans mon article précédent :
remplacer preg_quote($exp) par preg_quote($exp, '#') au cas où tu
pourrais trouver un '#' dans $exp !
Post by Olivier Masson
Si, au sein du script php, je cherche "aujourd'hui", ça ne fonctionne pas.
Normal, le problème est que le texte original transforme les ' en ’ (je
ne le contrôle pas).
Donc, toujours au sein du script, je cherche "aujourd’hui" et là, ça
fonctionne.
Par contre, quand j'utilise la sortie MySQL, ça ne fonctionne plus. J'ai
beau faire un str_replace("’","'",$texte) ou un
str_replace("'","’",$exp), ça ne fonctionne pas du moment que $exp vient
de la base de données.
Pour comprendre ce qui se passe réellement, il serait intéressant
d'avoir un « dump » hexadécimal du $exp et de $texte. Est-ce que
des caractères Unicode ne seraient pas ajoutés automatiquement quand
on rencontre un « ’ » ?
Post by Olivier Masson
Pourtant, quand je fais un echo du $exp sorti de la base et que je fais
un copier/coller dans le script, ça fonctionne.
Idem. Si le copier/coller ne recopie pas un caractère invisible du style
d'un BOM, cela pourrait peut-être expliquer le comportement.
Post by Olivier Masson
PS : pourquoi les mb_ utilisent les regex POSIX (y'a pas de mb_[p]reg)
alors qu'elles sont dépréciées ?
Problablement parce que tout le monde se fout des fonctions mb_*, vu que
le vrai standard est UTF-8 et que les fonctions preg_* savent très bien
les gérer avec l'option u ?
Olivier Miakinen
2009-10-16 14:34:56 UTC
Permalink
Post by Olivier Masson
preg_replace ( "#(\W)(" . preg_quote ( $exp ) . ")(\W)#Ui" ,
'${1}%${2}%${3}' , $texte , $max );
Tout d'abord, si les expressions $exp sont censées toujours commencer et
finir par un caractère « de mot », alors une assertion « limite de mot »
est plus facile à lire qu'un (\W) repris dans un ${1}. Qui plus est,
cela fonctionnera même en début de chaîne, ce qui n'est pas le cas avec
(\W).

preg_replace ( "#\b(" . preg_quote ( $exp ) . ")\b#Ui" , '%${1}%' ,
$texte , $max );

Personnellement j'ai l'habitude de respecter à peu près la typographie
en ce qui concerne les espaces à l'intérieur des parenthèses et avant
les virgules, d'autant que c'est la même en anglais et en français, mais
tu n'es bien sûr pas obligé de penser comme moi. Malgré tout je le fais
ici pour être sûr de ne rien oublier d'autre. Je supprime en général
aussi l'espace entre le nom d'une fonction et sa parenthèse ouvrante, et
je préfère utiliser $1 plutôt que ${1} (sauf bien sûr s'il est suivi
d'un chiffre, ce qui ne m'est jamais arrivé).

preg_replace("#\b(" . preg_quote($exp) . ")\b#Ui", '%$1%',
$texte, $max);

Tiens, je m'aperçois que tous les caractères servant au « matching »
sont utilisés, on peut donc encore économiser deux parenthèses et
(selon moi, mais c'est très subjectif) améliorer encore la lisibilité.

preg_replace("#\b" . preg_quote($exp) . "\b#Ui", '%$0%',
$texte, $max);

Maintenant, puisque tu dis que tout est en UTF-8, je pense que l'option
« u » (PCRE8) s'impose, d'autant que tu n'utilises aucune fonction
spécifique à PCRE. Si ça se trouve, c'est la seule source de tes soucis,
même si je n'en ai aucune idée parce que je n'ai pas encore vraiment
compris le problème.

preg_replace("#\b" . preg_quote($exp) . "\b#Uiu", '%$0%',
$texte, $max);

Voilà. Pour le reste on verra plus tard...
Olivier Masson
2009-10-16 16:37:19 UTC
Permalink
Post by Olivier Miakinen
preg_replace("#\b" . preg_quote($exp) . "\b#Ui", '%$0%',
$texte, $max);
Pour les espaces, je fais comme toi mais là, j'éclaircis à force de
modifications.
Oui, pour le \b ça doit fonctionner mais j'ai déjà rencontré des
problèmes avec son utilisation (surement de ma faute).
Et pour # dans preg_quote, il y est à l'origine, mais merci.
Post by Olivier Miakinen
Maintenant, puisque tu dis que tout est en UTF-8, je pense que l'option
« u » (PCRE8) s'impose, d'autant que tu n'utilises aucune fonction
spécifique à PCRE. Si ça se trouve, c'est la seule source de tes soucis,
même si je n'en ai aucune idée parce que je n'ai pas encore vraiment
compris le problème.
preg_replace("#\b" . preg_quote($exp) . "\b#Uiu", '%$0%',
$texte, $max);
Ben écoute, au moins j'aurais appris un truc car je n'avais jamais prêté
attention à l'option u ! Ca va m'alléger quelques scripts.

Pour mon problème, ça ne change rien. Ce que j'ai du mal à comprendre,
c'est qu'en fait, le quote, ce serait un /x92, typique de CP1252 alors
que c'est de l'utf-8 partout.
Lorsque je fais str_replace("’","'",$texte), le texte n'est pas modifié.
Par contre l'opération inverse sur $exp fonctionne (' se transforme bien
en ’).
Pourtant, à l'écran, ces deux ’ sont les mêmes. Y'a-t-il
translittération automatique qq part ?

Démonstration (en espérant que tout passe tel quel) :
iconv('Windows-1252' ,'UTF-8', $exp) : aujourd’hui
iconv('Windows-1252' ,'UTF-8', $texte) : aujourd’hui
iconv('UTF-8' ,'Windows-1252', $exp) : aujourd�hui
iconv('UTF-8' ,'Windows-1252', $texte) : aujourd’hui
iconv('iso-8859-1' ,'UTF-8', $exp) : aujourd’hui€™ (là, le cc ne
fonctionne pas)
iconv('iso-8859-1' ,'UTF-8', $texte) : aujourd’hui

J'en déduis bêtement que mon $exp est bien en utf-8 et mon $texte non.
Alors que la base et le champ sont en utf-8 et que mb_detect_encoding me
dit qu'il s'agit d'utf-8.

Où je deviens fou, c'est qu'en faisant :
str_replace("'",chr(146),$exp)
pour remplacer le ' de ma base par un \x92 bien moche qui est censé être
dans le texte, bien évidemment, ça ne fonctionne pas et ne s'affiche
même pas puisque chr(146) en utf-8, ça plait pas.

Pour finir, j'ai essayé un
str_replace("'","&#8217;",$exp), ce qui a bien remplacé le ' par un ’...
mais toujours pas considéré comme identique à celui du $texte.
Olivier Miakinen
2009-10-16 17:12:17 UTC
Permalink
Post by Olivier Masson
Pour mon problème, ça ne change rien. Ce que j'ai du mal à comprendre,
c'est qu'en fait, le quote, ce serait un /x92, typique de CP1252 alors
que c'est de l'utf-8 partout.
Ah, on avance.
Post by Olivier Masson
Lorsque je fais str_replace("’","'",$texte), le texte n'est pas modifié.
Par contre l'opération inverse sur $exp fonctionne (' se transforme bien
en ’).
Pourtant, à l'écran, ces deux ’ sont les mêmes. Y'a-t-il
translittération automatique qq part ?
iconv('Windows-1252' ,'UTF-8', $exp) : aujourd’hui
’ : E2 80 99, si le charset était Windows-1252. Puisque c'est le
résultat de iconv('Windows-1252', 'UTF-8'), on peut supposer que
$exp contient bien une apostrophe UTF-8 à l'origine.
Post by Olivier Masson
iconv('Windows-1252' ,'UTF-8', $texte) : aujourd’hui
Du coup, on peut supposer que $texte contient une apostrophe
Windows-1252 à l'origine.
Post by Olivier Masson
iconv('UTF-8' ,'Windows-1252', $exp) : aujourd�hui
Logique : il transforme une apostrophe UTF-8 en Windows-1252, et le
résultat n'est pas de l'UTF-8.
Post by Olivier Masson
iconv('UTF-8' ,'Windows-1252', $texte) : aujourd’hui
Ah zut, là je ne comprends pas comment c'est possible.
Post by Olivier Masson
iconv('iso-8859-1' ,'UTF-8', $exp) : aujourd’hui€™ (là, le cc ne
fonctionne pas)
Ça, cela reste logique : des trois codes \xE2, \x80 et \x99 d'origine,
seul le \xE2 existe en Latin1 ; les autres sont virés.
Post by Olivier Masson
iconv('iso-8859-1' ,'UTF-8', $texte) : aujourd’hui
Hum...
Post by Olivier Masson
J'en déduis bêtement que mon $exp est bien en utf-8 et mon $texte non.
Je ne te demande que deux tests :
bin2hex($exp)
bin2hex($texte)
Là on saura enfin ce qu'ils ont dans le ventre.
Post by Olivier Masson
Alors que la base et le champ sont en utf-8 et que mb_detect_encoding me
dit qu'il s'agit d'utf-8.
Une possibilité serait que l'apostrophe Windows-1252 ait été encodée en
UTF-8 *comme si* c'était du Latin1, ce qui donnerait C2 92 au lieu de
92 (Windows-1252 vrai) ou de E2 80 99 (UTF-8 vrai). Je pense que la
fonction utf8_encode doit faire ce genre de blague.
Post by Olivier Masson
str_replace("'",chr(146),$exp)
pour remplacer le ' de ma base par un \x92 bien moche qui est censé être
dans le texte, bien évidemment, ça ne fonctionne pas et ne s'affiche
même pas puisque chr(146) en utf-8, ça plait pas.
et str_replace("'", "\xC2\x99", $exp) ?
Post by Olivier Masson
Pour finir, j'ai essayé un
str_replace("'","&#8217;",$exp), ce qui a bien remplacé le ' par un ’...
mais toujours pas considéré comme identique à celui du $texte.
Oui, ça c'est normal. Ce sont deux représentations complètement différentes.

Cordialement,
--
Olivier Miakinen
Olivier Masson
2009-10-16 18:23:38 UTC
Permalink
Post by Olivier Miakinen
bin2hex($exp)
bin2hex($texte)
Là on saura enfin ce qu'ils ont dans le ventre.
Ah ben c'est sûr...
version base : 7465737420696369
version texte : 3c703e61756a6f7572642623383231373b6875693c2f703e0a
Au cas où, je signale que les accents, que ce soit dans la base ou le
texte passe très bien sur la page résultante encodée en utf-8.
Post by Olivier Miakinen
et str_replace("'", "\xC2\x99", $exp) ?
Gros caca à la place du '
Olivier Miakinen
2009-10-16 18:31:03 UTC
Permalink
Post by Olivier Masson
Post by Olivier Miakinen
bin2hex($exp)
bin2hex($texte)
Là on saura enfin ce qu'ils ont dans le ventre.
Ah ben c'est sûr...
version base : 7465737420696369
"test ici" ;-)
Post by Olivier Masson
version texte : 3c703e61756a6f7572642623383231373b6875693c2f703e0a
"<p>aujourd&#8217;hui</p>"

Ah, je comprends mieux pourquoi toutes les versions marchaient, quels
que soient les iconv() effectués ! Il n'y a que de l'ASCII ici, et c'est
juste à l'affichage que tu montres une apostrophe...
Olivier Masson
2009-10-17 19:56:22 UTC
Permalink
Post by Olivier Miakinen
Post by Olivier Masson
Post by Olivier Miakinen
bin2hex($exp)
bin2hex($texte)
Là on saura enfin ce qu'ils ont dans le ventre.
Ah ben c'est sûr...
version base : 7465737420696369
"test ici" ;-)
:) je ne parle pas hexadecimal couramment, me suis planté de ligne.

61 75 6a 6f 75 72 64 27 68 75 69
61 75 6a 6f 75 72 64 26 23 38 32 31 37 3b 68 75 69
Post by Olivier Miakinen
Post by Olivier Masson
version texte : 3c703e61756a6f7572642623383231373b6875693c2f703e0a
"<p>aujourd&#8217;hui</p>"
Ah, je comprends mieux pourquoi toutes les versions marchaient, quels
que soient les iconv() effectués ! Il n'y a que de l'ASCII ici, et c'est
juste à l'affichage que tu montres une apostrophe...
Mais pourquoi cette entité n'apparait nulle part (dans le code) ?
Olivier Miakinen
2009-10-17 21:23:07 UTC
Permalink
Post by Olivier Masson
61 75 6a 6f 75 72 64 27 68 75 69
aujourd'hui
Post by Olivier Masson
61 75 6a 6f 75 72 64 26 23 38 32 31 37 3b 68 75 69
aujourd&#8217;hui

Bon sang, mais c'est bien sûr ! Parmi toutes les modifications que
j'aurais faites à ta ligne de code, il y en a une dont je n'ai pas
parlé, c'est que je trouvais le caractère « # » peu lisible comme
délimiteur d'expression rationnelle ; je n'en ai pas parlé car encore
une fois la lisibilité est quelque chose de subjectif. Mais ici, il
n'est pas question que de lisibilité : tu as un « # » dans la chaîne
elle-même ! Ah, sauf que tu dis que tu le passes bien en paramètre ?
Bon, eh bien je n'en sais rien.
Post by Olivier Masson
Post by Olivier Miakinen
Post by Olivier Masson
version texte : 3c703e61756a6f7572642623383231373b6875693c2f703e0a
"<p>aujourd&#8217;hui</p>"
Ah, je comprends mieux pourquoi toutes les versions marchaient, quels
que soient les iconv() effectués ! Il n'y a que de l'ASCII ici, et c'est
juste à l'affichage que tu montres une apostrophe...
Mais pourquoi cette entité n'apparait nulle part (dans le code) ?
Ça, c'est à toi de nous le dire car tu es le seul à l'avoir, le code.
Sans infos supplémentaires, j'ai même cru que c'était bien dans le code
et que tu avais oublié de faire « View > Source » sur la page HTML.
--
Olivier Miakinen
Olivier Masson
2009-10-18 19:01:41 UTC
Permalink
Post by Olivier Masson
Post by Olivier Masson
61 75 6a 6f 75 72 64 27 68 75 69
aujourd'hui
Post by Olivier Masson
61 75 6a 6f 75 72 64 26 23 38 32 31 37 3b 68 75 69
aujourd&#8217;hui
Bon sang, mais c'est bien sûr ! Parmi toutes les modifications que
j'aurais faites à ta ligne de code, il y en a une dont je n'ai pas
parlé, c'est que je trouvais le caractère « # » peu lisible comme
délimiteur d'expression rationnelle ; je n'en ai pas parlé car encore
une fois la lisibilité est quelque chose de subjectif. Mais ici, il
n'est pas question que de lisibilité : tu as un « # » dans la chaîne
elle-même ! Ah, sauf que tu dis que tu le passes bien en paramètre ?
Bon, eh bien je n'en sais rien.
Ç'aurait effectivement pu être la bonne solution, pas évidente à trouver.
En fait, je viens à l'instant de voir une erreur que j'avais faite.
Comme je ne peux pas modifier ce qui vient de $texte, j'ai voulu
modifier ce qui provenait de la base. Et là, je ne comprenais vraiment
pas pourquoi ça ne fonctionnait pas. Et puis avec ta très bonne idée du
binhex, ça devenait plus facile à voir.
Je faisais (depuis tes infos sur cet étrange &#8217) :
str_replace("'", "&#8217",$exp);

Ben oui, c'est béta hein :) Il manquait juste le ;.
Donc maintenant ça fonctionne !

Merci beaucoup pour ton aide.
Olivier Miakinen
2009-10-18 19:45:51 UTC
Permalink
Post by Olivier Masson
[...]
str_replace("'", "&#8217",$exp);
Ben oui, c'est béta hein :) Il manquait juste le ;.
Donc maintenant ça fonctionne !
D'autant plus béta que dans <4ad89fed$0$10119$***@news.free.fr>
tu avais bien écrit :
<cit.>
Pour finir, j'ai essayé un
str_replace("'","&#8217;",$exp), ce qui a bien remplacé le ' par un ’...
</cit.>
... ce qui fait que je n'ai pas pu le corriger ici.
Post by Olivier Masson
Merci beaucoup pour ton aide.
Avec plaisir.
--
Olivier Miakinen
Olivier Miakinen
2009-10-16 19:09:44 UTC
Permalink
Post by Olivier Masson
Post by Olivier Miakinen
bin2hex($exp)
bin2hex($texte)
version base : 7465737420696369
version texte : 3c703e61756a6f7572642623383231373b6875693c2f703e0a
Pour la prochaine fois, plutôt qu'un simple bin2hex($exp) dont le
résultat est un peu trop compact, je te suggère :
chunk_split(bin2hex($exp), 2, " ");
Olivier Masson
2009-10-24 10:16:54 UTC
Permalink
Post by Olivier Miakinen
Post by Olivier Masson
preg_replace ( "#(\W)(" . preg_quote ( $exp ) . ")(\W)#Ui" ,
'${1}%${2}%${3}' , $texte , $max );
Tout d'abord, si les expressions $exp sont censées toujours commencer et
finir par un caractère « de mot », alors une assertion « limite de mot »
est plus facile à lire qu'un (\W) repris dans un ${1}. Qui plus est,
cela fonctionnera même en début de chaîne, ce qui n'est pas le cas avec
(\W).
preg_replace ( "#\b(" . preg_quote ( $exp ) . ")\b#Ui" , '%${1}%' ,
$texte , $max );
En fait, ça ne fonctionne pas avec /b car il n'isole pas "isoloir" dans
"l'isoloir".
Olivier Miakinen
2009-10-24 11:54:17 UTC
Permalink
Post by Olivier Masson
Post by Olivier Miakinen
Post by Olivier Masson
preg_replace ( "#(\W)(" . preg_quote ( $exp ) . ")(\W)#Ui" ,
'${1}%${2}%${3}' , $texte , $max );
Tout d'abord, si les expressions $exp sont censées toujours commencer et
finir par un caractère « de mot », alors une assertion « limite de mot »
est plus facile à lire qu'un (\W) repris dans un ${1}. Qui plus est,
cela fonctionnera même en début de chaîne, ce qui n'est pas le cas avec
(\W).
preg_replace ( "#\b(" . preg_quote ( $exp ) . ")\b#Ui" , '%${1}%' ,
$texte , $max );
En fait, ça ne fonctionne pas avec /b
\b
Post by Olivier Masson
car il n'isole pas "isoloir" dans "l'isoloir".
Hein ? Alors « ' » fait partie de \W, « i » de \w, mais le \b ne matche
pas au milieu de « 'i » ??? Je viens de faire des tests, et pour moi ça
marche -- conformément à la doc.
--
Olivier Miakinen
Olivier Masson
2009-10-24 19:12:32 UTC
Permalink
Post by Olivier Miakinen
Hein ? Alors « ' » fait partie de \W, « i » de \w, mais le \b ne matche
pas au milieu de « 'i » ??? Je viens de faire des tests, et pour moi ça
marche -- conformément à la doc.
Je retire, jma trompé !
C'est plus tordu : sur mon serveur en local, tout fonctionne. Par
contre, sur un serveur Amen (oui, je sais, c'est mauvais, mais ce n'est
pas le mien), ça ne fonctionne pas. Pas à cause de l'apostrophe comme je
l'ai cru mais à cause de l'accent.

Donc l'exemple avec l'isoloir, on oublie, j'ai fait n'importe quoi.
Par contre, sur le serveur Amen, "étude" n'était pas trouvé.
J'ai donc comparé avec bin2hex mais cette fois, le problème ne venait
pas des chaines.
C'est bel et bien le preg-replace qui ne fonctionnait pas.

Je t'avais dit que j'avais déjà rencontré des problèmes avec \b. Ça n'a
pas loupé : j'y ai encore une fois eu le droit.
Tout fonctionne avec \W.

Par contre pourquoi, ça, aucune idée. Pas eu le tps de tester sur un
serveur linux à moi.
Olivier Miakinen
2009-10-24 20:19:04 UTC
Permalink
Post by Olivier Masson
Je retire, jma trompé !
C'est plus tordu : sur mon serveur en local, tout fonctionne. Par
contre, sur un serveur Amen (oui, je sais, c'est mauvais, mais ce n'est
pas le mien), ça ne fonctionne pas. Pas à cause de l'apostrophe comme je
l'ai cru mais à cause de l'accent.
[...] sur le serveur Amen, "étude" n'était pas trouvé.
Bon sang mais c'est bien sûr ! Et pour le coup c'est Amen qui a raison,
en utilisant problablement une locale "C" alors qu'en local tu dois être
en français. Tu dois avoir parfois des comportements assez inattendus
sur ton serveur local.
Post by Olivier Masson
[...]
Je t'avais dit que j'avais déjà rencontré des problèmes avec \b. Ça n'a
pas loupé : j'y ai encore une fois eu le droit.
Tout fonctionne avec \W.
Oui, mais ça ne marchera pas dans tous les cas. Par exemple, si tu
cherches « change » il le trouvera dans « échange », et si tu cherches
« coup » il le trouvera dans « découpât ».
Post by Olivier Masson
Par contre pourquoi, ça, aucune idée. Pas eu le tps de tester sur un
serveur linux à moi.
La raison est très simple. Avec une locale française, « é » et « â »
font partie de \w alors qu'avec la locale "C" ils font partie de \W.

Du coup, puisque tes chaînes sont en UTF-8 je te suggère d'utiliser des
assertions, avec la propriété Unicode \P{L} ou \PL qui signifie « n'est
pas une lettre » (quelle que soit la langue) :

preg_replace("/(?<=\PL)" . preg_quote($exp) . "(?=\PL)/Uiu",
'%$0%', $texte, $max);

Voire, pour gérer le cas du début ou de la fin de texte :

preg_replace("/(?<=^|\PL)" . preg_quote($exp) . "(?=\PL|$)/Uiu",
'%$0%', $texte, $max);

http://fr.php.net/manual/fr/regexp.reference.assertions.php
http://fr.php.net/manual/fr/regexp.reference.circudollar.php
http://fr.php.net/manual/fr/regexp.reference.unicode.php
--
Olivier Miakinen
Olivier Masson
2009-10-26 16:08:30 UTC
Permalink
Post by Olivier Miakinen
Bon sang mais c'est bien sûr ! Et pour le coup c'est Amen qui a raison,
Ah merde !
Post by Olivier Miakinen
Du coup, puisque tes chaînes sont en UTF-8 je te suggère d'utiliser des
assertions, avec la propriété Unicode \P{L} ou \PL qui signifie « n'est
preg_replace("/(?<=\PL)" . preg_quote($exp) . "(?=\PL)/Uiu",
'%$0%', $texte, $max);
preg_replace("/(?<=^|\PL)" . preg_quote($exp) . "(?=\PL|$)/Uiu",
'%$0%', $texte, $max);
http://fr.php.net/manual/fr/regexp.reference.assertions.php
http://fr.php.net/manual/fr/regexp.reference.circudollar.php
http://fr.php.net/manual/fr/regexp.reference.unicode.php
Ouah ! Bon, je n'ai pas encore testé mais chapeau !
Je n'avais jamais vu \P.
Tu devrais faire un conf sur unicode à Paris Web ? :)

Je craignais qu'une limite de mot et ce qui est ou n'est pas un mot
pouvait être gênant car je n'ai jamais trouvé (cherché ?) de définitions
exactes de ces classes.

Bon, je ne te remercie pas parce que c'est un peu moi qui t'ai donné la
solution, que j'ai eu l'extrême gentillesse de partager avec le peuple !
Mais bon, merci qd même beaucoup ;)
Olivier Miakinen
2009-10-26 16:26:05 UTC
Permalink
Post by Olivier Masson
... c'est Amen qui a raison,
Ah merde !
Non, Amen. Enfin... tu le prononces comme tu veux.
Post by Olivier Masson
Je n'avais jamais vu \P.
Problablement parce que tu ne connaissais pas non plus l'option /u
(PCRE8). Attention, l'un ne va pas sans l'autre !

<cit. http://fr2.php.net/manual/fr/reference.pcre.pattern.modifiers.php>
u (PCRE8)

Cette option désactive[sic] les fonctionnalités additionnelles de PCRE
qui ne sont pas compatibles avec Perl. Les chaînes sont traitées comme
des chaînes UTF-8. Cette option est disponible en PHP 4.1.0 et plus
récent sur plate-forme Unix et en PHP 4.2.3 et plus récent sur
plate-forme Windows.
</cit.>

En version originale, sans les coquilles de traduction :

<cit. http://fr2.php.net/manual/en/reference.pcre.pattern.modifiers.php>
u (PCRE8)

This modifier turns on additional functionality of PCRE that is
incompatible with Perl. Pattern strings are treated as UTF-8. This
modifier is available from PHP 4.1.0 or greater on Unix and from
PHP 4.2.3 on win32. UTF-8 validity of the pattern is checked since
PHP 4.3.5.
</cit.>
Post by Olivier Masson
Bon, je ne te remercie pas parce que c'est un peu moi qui t'ai donné la
solution, que j'ai eu l'extrême gentillesse de partager avec le peuple !
:-D
Olivier Masson
2009-10-27 10:50:17 UTC
Permalink
!!!
C'est précisément ce que je ne comprenais pas !
Je ne voyais pas trop à quoi ils faisaient allusion, mais je trouvais ça
dommage de désactiver des fonctions en passant en utf-8...
Olivier Miakinen
2009-10-27 11:34:09 UTC
Permalink
Post by Olivier Masson
!!!
C'est précisément ce que je ne comprenais pas !
Oui, et je m'étais fait avoir dans l'une de mes premières réponses.
Je viens de tenter de joindre le groupe de discussions des traducteurs
de la doc PHP en français, je verrai bien si je peux contribuer à
corriger toutes ces coquilles : <http://news.php.net/php.doc.fr/7393>.
Loading...