14 votes

correspondance entre les limites des mots de l'expression rationnelle php en utf-8

J'ai le code php suivant dans un fichier php utf-8 :

var_dump(setlocale(LC_CTYPE, 'de_DE.utf8', 'German_Germany.utf-8', 'de_DE', 'german'));
var_dump(mb_internal_encoding());
var_dump(mb_internal_encoding('utf-8'));
var_dump(mb_internal_encoding());
var_dump(mb_regex_encoding());
var_dump(mb_regex_encoding('utf-8'));
var_dump(mb_regex_encoding());
var_dump(preg_replace('/\bweiß\b/iu', 'weiss', 'weißbier'));

Je voudrais que la dernière regex ne remplace que les mots complets et non les parties de mots.

Sur mon ordinateur Windows, il revient :

string 'German_Germany.1252' (length=19)
string 'ISO-8859-1' (length=10)
boolean true
string 'UTF-8' (length=5)
string 'EUC-JP' (length=6)
boolean true
string 'UTF-8' (length=5)
string 'weißbier' (length=9)

Sur le serveur web (linux), j'obtiens :

string(10) "de_DE.utf8"
string(10) "ISO-8859-1"
bool(true)
string(5) "UTF-8"
string(10) "ISO-8859-1"
bool(true)
string(5) "UTF-8"
string(9) "weissbier"

Ainsi, la regex fonctionne comme prévu sous Windows mais pas sous Linux.

La question principale est donc la suivante : comment dois-je écrire mon expression rationnelle pour qu'elle ne corresponde qu'aux limites des mots ?

Une question secondaire est de savoir comment je peux faire savoir à Windows que je veux utiliser utf-8 dans mon application php.

19voto

Alan Moore Points 39365

Même en mode UTF-8, les raccourcis de classe standard comme \w y \b ne sont pas sensibles à l'Unicode. Il suffit d'utiliser les raccourcis Unicode, comme vous l'avez fait, mais vous pouvez rendre les choses un peu moins laides en utilisant des palliatifs au lieu d'alternances :

/(?<!\pL)weiß(?!\pL)/u

Remarquez également que je n'ai pas mis d'accolades dans les raccourcis de classe Unicode ; vous pouvez le faire lorsque le nom de la classe est composé d'une seule lettre.

5voto

bobble bubble Points 6095

Je suppose que c'était lié à Bogue n° 52971

PCRE-Meta-Characters comme \b \w ne fonctionne pas avec les chaînes unicode.

et corrigé en PHP 5.3.4

Extension PCRE : Correction du bogue #52971 ( PCRE-Meta-Characters ne fonctionne pas avec utf-8 ).

4voto

tomsv Points 2565

Voici ce que j'ai trouvé jusqu'à présent. En réécrivant les modèles de recherche et de remplacement comme ceci :

$before = '(^|[^\p{L}])';
$after = '([^\p{L}]|$)';
var_dump(preg_replace('/'.$before.'weiß'.$after.'/iu', '$1weiss$2', 'weißbier'));
// Test some other cases:
var_dump(preg_replace('/'.$before.'weiß'.$after.'/iu', '$1weiss$2', 'weiß'));
var_dump(preg_replace('/'.$before.'weiß'.$after.'/iu', '$1weiss$2', 'weiß bier'));
var_dump(preg_replace('/'.$before.'weiß'.$after.'/iu', '$1weiss$2', ' weiß'));

J'obtiens le résultat souhaité :

string 'weißbier' (length=9)
string 'weiss' (length=5)
string 'weiss bier' (length=10)
string ' weiss' (length=6)

à la fois sur mon ordinateur Windows exécutant apache et sur le serveur web linux hébergé exécutant apache.

Je suppose qu'il existe une meilleure façon de procéder.

Par ailleurs, j'aimerais toujours mettre mon ordinateur Windows en utf-8.

0voto

ntd Points 4244

Según ce commentaire il s'agit d'un bug de PHP. Est-ce que l'utilisation de \W au lieu de \b donner un avantage quelconque ?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X