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

Répondre


Cette question est un moyen d’empêcher des soumissions automatisées de formulaires par des robots.
Smileys
:D :) :( :o :shock: :? 8-) :lol: :x :P :oops: :cry: :evil: :twisted: :roll: :wink: :!: :?: :idea: :arrow: :| :mrgreen: =D> #-o =P~ :^o :non: :priere: 8-|
Voir plus de smileys
  Revue du sujet
 

  Étendre la vue Revue du sujet : Expressions régulières et accents & cédilles

par Ripat » 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.

par AB » 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.

par abelthorne » 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). :?:

par raptor » 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 "à" ^^

par jojolapine » 13 mars 2007, 12:48

par abelthorne » 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 ?

par Ryle » 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

:)

par abelthorne » 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.

par raptor » 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 ?

par jojolapine » 13 mars 2007, 12:02

utilise preg_match() pour faire ce que tu veux....

par abelthorne » 13 mars 2007, 11:52

À la base, je veux tester un nom propre, je pars donc du principe qu'il pourra contenir des lettres majuscules et minuscules, un trait d'union, une apostrophe et une espace.
Je teste donc ma chaîne comme suit :

Code : Tout sélectionner

function testenom($chaine){ if(ereg("^[A-Za-z' -]+$",$chaine)) return true; else return false; }
(Je précise que j'ai récupéré la chaîne en question dans un bouquin.)

Tout va bien tant que je n'ai pas de caractères spéciaux. En faisant des tests (sur le terme "Besançon", par exemple), je me suis aperçu qu'avec la présence de la cédille ma fonction me renvoyait "false".
Après, j'ai essayé des caractères accentués, pareil. Comme j'étais en train de tester une chaîne avec un "à" dedans, je l'ai ajouté à la fin et je me suis aperçu que d'un seul coup, la fonction était vérifiée aussi pour les autres caractères accentués et la cédille. D'où mon étonnement et mon message sur le forum.
Seulement, je crois comprendre qu'en fait j'ai rajouté un intervalle entre l'espace et le "à" et que ça a été un peu le hasard que ma fonction marche (je suppose que les autres caractères que j'ai testés étaient dans la plage en question dans le code ASCII).

Donc, je cherche à créer une expression régulière qui teste un nom propre avec toutes les subtilités syntaxiques européennes sans avoir à rajouter tous les caractères spéciaux parce que je risque d'en oublier (sorti des accents grave, aigus, circonflexes, trémas & cécilles, il y a encore des caractères nordiques avec un cercle au-dessus, le tilde sur le n espagnol, etc. ; sans compter qu'il faut alors que je les rajoute en majuscule et minuscule).

par raptor » 13 mars 2007, 11:39

Fait voir le morceau de code concerné ca sera plus simple pour commencer.

par abelthorne » 13 mars 2007, 11:19

regarde l'url que j'ai mis plus haut... :roll:
J'ai regardé, justement, et je crois bien que les résultats ne sont pas les mêmes chez moi.
Je vais regarder ça plus en détail quand j'aurai réussi à reprendre le fil de la discussion. :)

EDIT : petite question : que signifie "(ne pas oublier les délimiteurs pour les pcre!)" concernant la fonction ereg ? C'est justement avec elle que je teste mes expressions et aucune de celles que je rentre sur ton site ne me donne de résultats.

EDIT 2 : au temps pour moi concernant la position de "à" dans ma chaîne : ça ne marche effectivement que si je le place après le tiret (il doit être considéré comme fin de plage et ça expliquerait peut-être pourquoi ça me reconnaît alors d'autres caractères accentués).

par jojolapine » 13 mars 2007, 11:15

regarde l'url que j'ai mis plus haut... :roll:

par abelthorne » 13 mars 2007, 11:13

je crois que tu n'as pas compris ce que je veux dire. Il faut que ton "à" soit avant le "-", sinon tout ce qui ne contient pas "à" est vrai.
Enfin perso je viens de tester et ca marche tout a fait en faisant le masque comme ca : "^[A-Za-z' à-]+$"
Mmm... Personnellement, si je mets le "à" avant ou après le tiret, il n'y a aucune différence au niveau de mes tests (ce qui me semble logique étant donné que le caractère de rejet est le ^). Par contre, si je ne mets pas le "à" du tout (ou "é" ou autre), tous les caractères accentués sont rejetés.
Remplace la valeur de $str, ca fonctionne bien pour les chaines ayant "à" , mais ca fonctionne pas sur "besançon". Si par contre tu rajoutes "ç" dans le masque, ca fonctionne.
Bizarre, ça ne semble pas marcher de la même façon de mon côté. Est-ce que ce serait ma config PHP en local qui pose problème ?