Expressions régulières et accents & cédilles

Mammouth du PHP | 543 Messages

13 mars 2007, 12:18

Code : Tout sélectionner

function testenom($chaine){ if(ereg("^[A-Za-z' -]+$",$chaine)) return true; else return false; }
.
Avec un tel masque donc, lyon passe, mais pas besançon on est d'accord ?

Eléphant du PHP | 92 Messages

13 mars 2007, 12:24

utilise preg_match() pour faire ce que tu veux....
Je viens de tester mais j'ai un autre souci. Je ne suis pas trop sûr de la syntaxe et j'ai remplacé mon ereg() par preg_match("#[A-Za-z' -]+#",$chaine).
Seulement, si je rajoute des chiffres après le premier caractère, l'expression se vérifie et je ne comprends pas bien pourquoi...
- "bob" renvoie vrai (c'est bon)
- "5" renvoie faux (c'est toujours bon)
- "bob5" renvoie vrai (ça ne va plus)

Et je m'aperçois que des caractères spéciaux tels que "$" sont acceptés par mon expression (aussi bien avec ereg() qu'avec preg_match()).

Je comprends de moins en moins les expressions régulières...

Code : Tout sélectionner

function testenom($chaine){ if(ereg("^[A-Za-z' -]+$",$chaine)) return true; else return false; }
.
Avec un tel masque donc, lyon passe, mais pas besançon on est d'accord ?
On est d'accord en pratique. Je pensais d'abord que le "ç" était équivalent à "c" et donc que le test se vérifierait. Comme en pratique ce n'est pas le cas, je cherche un moyen de tester tous les caractères spéciaux possibles dans un nom propre sans problème.

EDIT : par contre, en modifiant le masque comme suit : "^[A-Za-z' -à]+$", "Besançon" passe aussi et je ne suis pas bien sûr de comprendre pourquoi.

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 10684 Messages

13 mars 2007, 12:36

EDIT : par contre, en modifiant le masque comme suit : "^[A-Za-z' -à]+$", "Besançon" passe aussi et je ne suis pas bien sûr de comprendre pourquoi.
Je plussois ce qui a déjà été dit, si tu veux autoriser le caractère "-" dans ton masque, il doit obligatoirement être placé à la fin du masque.
En effet, le "moins" a également pour effet de déterminer un interval : a-z, A-Z... C'est ce qu'il fait s'il n'est pas le dernier caractère du masque.

Voici concrètement ce que donnent tes masques :

"^[A-Za-z' -à]+$",
- Tous les caractères de A à Z
- Tous les caractères de a à z
- l'apostrophe
- Tous les caractères de "espace" à "à"

"^[A-Za-z' à-]+$",
- Tous les caractères de A à Z
- Tous les caractères de a à z
- l'apostrophe
- l'espace
- le tiret

:)
Ce n'est pas en améliorant la bougie que l'on a inventé l'ampoule...

Eléphant du PHP | 92 Messages

13 mars 2007, 12:43

Donc pour tester mes caractères spéciaux, je devrais pouvoir définir un intervalle entre le premier caractère et le dernier. Mais où est-ce que je peux trouver la liste de l'ordre des caractères testés par les expressions régulières ?

ViPHP
ViPHP | 3607 Messages

13 mars 2007, 12:48


Mammouth du PHP | 543 Messages

13 mars 2007, 12:56

Je plussois ce qui a déjà été dit, si tu veux autoriser le caractère "-" dans ton masque, il doit obligatoirement être placé à la fin du masque.
En effet, le "moins" a également pour effet de déterminer un interval : a-z, A-Z... C'est ce qu'il fait s'il n'est pas le dernier caractère du masque.
Merci pour le plussoiement, je le répète depuis mon premier post en lui demandant de déplacer son "à" ^^

Eléphant du PHP | 92 Messages

13 mars 2007, 12:59

ui demandant de déplacer son "à" ^^
Mais, euh, j'avais mal fait mes tests.

Sinon, je pensais bien évidemment à la table ASCII (et plus probablement à la version ANSI), mais si les intervalles sont bien définis par rapport à elle, je ne m'explique pas comment mon intervalle " -à" peut inclure le c cédille et les e accentués (qui se trouvent après le "à" dans la table ASCII étendue, quelle que soit sa version). :?:

ViPHP
AB
ViPHP | 5818 Messages

15 mars 2007, 16:06

Bonjour,

1/
Sinon, je pensais bien évidemment à la table ASCII (et plus probablement à la version ANSI), mais si les intervalles sont bien définis par rapport à elle, je ne m'explique pas comment mon intervalle " -à" peut inclure le c cédille et les e accentués (qui se trouvent après le "à" dans la table ASCII étendue, quelle que soit sa version). :?:
D'après mes tests, l'interval des classes fonctionne bien sur la table ASCII mais pas sur la tale ASCII étendue et le " -à" renvoie à peu près n'importe quoi. Donc plutôt que d'essayer de faire un interval sur les caractères accentués pourquoi ne pas lister ceux que tu souhaites autoriser.

2/
Je viens de tester mais j'ai un autre souci. Je ne suis pas trop sûr de la syntaxe et j'ai remplacé mon ereg() par preg_match("#[A-Za-z' -]+#",$chaine).
Seulement, si je rajoute des chiffres après le premier caractère, l'expression se vérifie et je ne comprends pas bien pourquoi...
- "bob" renvoie vrai (c'est bon)
- "5" renvoie faux (c'est toujours bon)
- "bob5" renvoie vrai (ça ne va plus)

Et je m'aperçois que des caractères spéciaux tels que "$" sont acceptés par mon expression (aussi bien avec ereg() qu'avec preg_match()).
Tu te mélanges les pinceaux...évidemment que "bob5" renvoie vrai puisque tu testes si "bob5" contient des lettres et c'est vrai!

Il faut t'y prendre autrement et regarder si des caractères non autorisés sont présents donc
if(preg_match("#[^A-Za-z' -]+#",$chaine)) echo 'chaine ne convient pas';else echo 'chaine ok';

//ou
if(!preg_match("#[^A-Za-z' -]+#",$chaine)) echo 'chaine ok';else echo 'chaine ne convient pas';

//et pour rajouter des caractères accentués en minuscules, mieux vaut les lister
if(!preg_match("#[^A-Za-z'àáâãäåçèéêëìíîïðòóôõöùúûüýÿ -]+#",$chaine)) echo 'chaine ok';else echo 'chaine ne convient pas';

//Si tu acceptes les majuscules et minuscules accentuées ou non
if(!preg_match("#[^a-z'àáâãäåçèéêëìíîïðòóôõöùúûüýÿ -]+#i",$chaine)) echo 'chaine ok';else echo 'chaine ne convient pas';
  
//et pour éviter de renvoyer ok sur une chaine vide
if(!preg_match("#[^a-z'àáâãäåçèéêëìíîïðòóôõöùúûüýÿ -]+#i",$chaine) && trim($chaine) != '') echo 'chaine ok';else echo 'chaine ne convient pas';
Comme ça tu as une expression compréhensible qui ne devrait pas trop de donner de mauvaise surprise.

ViPHP
ViPHP | 1380 Messages

15 mars 2007, 19:34

J'ai lu en diagonale et je pense comprendre qu'il s'agit de trouver une classe de caractères qui comprenne les accents et autres particularités du jeux de caractère Fr.

Les classes [a-z] ne les comprennent pas mais la classe [[:alpha:]] et la classe PCRE \w bien. A condition que la locale Fr soit bien définie sur le serveur. Petit exemple:
// on force la locale à C
echo '<pre>', setlocale(LC_CTYPE, ''), "\r\n";

echo (int) preg_match('#\w#', 'é'), "\r\n";
echo (int) preg_match('#[a-z]#', 'é'), "\r\n";
echo (int) preg_match('#[[:alpha:]]#', 'é'), "\r\n\r\n";

// mise de la locale à fr_FR
echo setlocale(LC_CTYPE, 'fr_FR.ISO-8859-1'), "\r\n";

echo (int) preg_match('#\w#', 'é'), "\r\n";
echo (int) preg_match('#[a-z]#', 'é'), "\r\n";
echo (int) preg_match('#[[:alpha:]]#', 'é'), "\r\n";
Retournera:

Code : Tout sélectionner

C 0 0 0 fr_FR.ISO-8859-1 1 0 1
Attention que ceci dépend des locales installées sur le serveur. Pour en avoir la liste sous Linux:

Code : Tout sélectionner

$ locale -a
Edit: erreur typographique.
ripat