expressions régulières preg_match()

Eléphant du PHP | 190 Messages

02 oct. 2009, 10:21

Bonjour, petit problèmes d'expressions régulière. Voici mon code
$chaine=trim($_POST['apercu']);
if(preg_match("#^[a-zA-ZÀÁÂÃÄÅÇÈÉÊËÌÍÎÏÒÓÔÕÖÙÚÛÜÝàáâãäåçèéêëìíîïðòóôõöùúûüýÿ ',.:-]{9,70}$#",$chaine))
	{
	echo $chaine;
	}
else
	{
	echo"<p>Les champs sont mal remplis.</p>";
	echo $chaine;
	}
le problème c'est qu'il ne prend aucun de mes caractères accentués. J'ai beau retourner le problème dans tout les sens je ne comprend pas.

Pour info, les données sont récupérée d'un champ de formulaire <input type="text">

edit: Bon bon je comprend de moins en moins, j'ai mis une chaine de caractère (qui ne passe pas sur ma page) dans une variable. Elle passe très bien par la variable ... ca doit donc venir de mes champs ???
Modifié en dernier par Zahnzao le 02 oct. 2009, 19:55, modifié 2 fois.

Mammouth du PHP | 2937 Messages

02 oct. 2009, 11:48

La chaîne qui pose problème contiendrait-elle, par hasard, des \ une fois récupérée de ton champ, alors que la saisie ne comprend pas ce caractère ?

Si c'est le cas, ça veut dire que la directive magic_quotes_gpc est activée (ce qui a pour effet d'échapper automatiquement les caractères spéciaux contenus dans les chaînes envoyées par les méthodes GET, POST et COOKIE).

Je te conseille de modifier le début de ton code comme suit :
$chaine = (get_magic_quotes_gpc ())? trim (stripslashes ($_POST['apercu'])): trim ($_POST['apercu']);

Eléphant du PHP | 190 Messages

02 oct. 2009, 12:06

Non pas de \ dans la chaine récupérée. J'ai quand même testé et ca ne change rien.

pour expliquer plus clairement.

Le champ apercu était créer dynamiquement par un script javascript. c'était en fait la concaténation de 8 champs. Pensant que ca venait de la, j'ai un peu modofié mon script de manière a concaténer les champs en php sans récuperer le champ apercu.
if(isset($_POST['submit']))
	{
	$chaine=$_POST['mot1'].$_POST['ponctuation1']." ".$_POST['mot2'].$_POST['ponctuation2']." ".$_POST['mot3'].$_POST['ponctuation3']." ".$_POST['mot4'].$_POST['ponctuation4'];
	echo $chaine;
	if(preg_match("#^[a-zA-Zàçèéê ',.:-]{9,70}$#",$chaine))
		{
		echo"<p>Les champs sont bien remplis.</p>";
		}
	else
		{
		echo"<p>Les champs sont mal remplis.</p>";
		}
	}
De cette manière, les données envoyées sont écrite manuellement et non issues de variables Javascript.
Mais malheureusement ca ne change rien. Il refuse systématiquement tout mes (à ç è é ê).

edit: mon echo renvoie exactement la chaine telle quelle, c'est la que je comprend pas ... je suis perdu. Et ma regex passe sans problemes sur plusieurs testeurs en ligne dispo sur le net ...

Mammouth du PHP | 2937 Messages

02 oct. 2009, 12:26

Essaie avec l'expression rationnelle suivante :
preg_match ('#^[[:alnum:][:space:][:punct:]]{9,70}$#', $chaine);
Cela dit, ma suggestion précédente est toujours bonne à prendre et t'évitera des désagréments liées aux \. ;)

Eléphant du PHP | 190 Messages

02 oct. 2009, 12:38

Ca marche !

donc ca venait de l'expression... Par contre le [:punct:] accepte beaucoup trop de cractères a mon gout :( et si je je l'enlève, il ne prend plus plus mes éèà et tout le tralala ... je vais essayer de les exclures par la suite.

j'ai aussi remplacé le alnum par alpha car je ne veux pas de chiffres.

Merci à toi ;)

ViPHP
ViPHP | 3607 Messages

02 oct. 2009, 16:02

Tu es sûr que tu n'as pas un htmlentities() ou htmlentities() qui traine?
parce que si enlever [:punct:] fait que les accents ne sont plus acceptés, ça m'étonnerais pas, qu'ils soient transformé en &eacut; ou autre...

Eléphant du PHP | 190 Messages

02 oct. 2009, 16:55

non il n'y avait rien de tout ca, mon code était tel que je l'ai mis ici.

Du coup j'ai tout modifié. Au lieu de mettre dans la regex les caractères acceptés, j'ai exclu ceux que je ne voulais pas ... ca raccourcis mon code et c'est plus clair :p surtout que je me suis rendu compte qu'il me fallait finalement les chiffres ... alors tant qu' a faire...
preg_match ('#^[^\#\^\$\(\)\[\]\{\}\+\*\\\|<>&@"²³%µ]{9,100}$#', $chaine);
Merci pour votre aide ;)

Mammouth du PHP | 985 Messages

02 oct. 2009, 17:26

Oui je me suis aperçue de cela il n'y a pas très longtemps.
L'utilisation d'expressions régulières en prenant en compte les caractères accentués complique énormément le filtre.

Même chose avec la fonction ctype().
(Précision; c'était pour trouver une fonction ctype() acceptant les caractères accentués mais pas les autres caractères spéciaux et pas les retour à la ligne -> je n'ai pas réussis avec cette méthode).

Apparemment le problème se montre surtout, je croie, avec l'encodage UTF-8.

Ca devient un vrai casse-tête quand tu veux faire un filtre efficace prenant en compte les caractères accentués mais n'acceptant pas les autres caractères spéciaux.

Maintenant je ne sais pas si cela était la raison de ton soucis, mais cela m'a fait pensé a cela...

Ps:
je précise que c'est compliqué pour moi, pour les autres je ne sais pas :wink:


[EDIT]
L'explication a cela, est peut-être que dans la langue de Shakespear -> il n'y a pratiquement pas de caractères accentués.
Enfin c'est ma propre déduction...

[EDIT 2]
D'ailleurs si quelqu'un a une méthode simple -> je suis preneur aussi :)
Face à la roche, le ruisseau l'emporte toujours, non pas par la force mais par la persévérance.

Eléphant du PHP | 190 Messages

02 oct. 2009, 18:30

Apparemment le problème se montre surtout, je croie, avec l'encodage UTF-8.
Je crois que le soucis viens de la. Parceque la chaine directement dans une variable puis traitée avec preg_match() passe sans soucis, alors que les données issues du formulaire (la même chaine donc sans traitement au préalable avec htmlentities() ou htmlspecialchars() ) ne passe pas.

Mammouth du PHP | 985 Messages

02 oct. 2009, 18:49

Ok mais ne pas confondre encodage et conversion de caractères spéciaux avec htmlentities() ou htmlspecialchars().
Tout en présisant que htmlspecialchars() ne convertit pas les caractères accentués..
Face à la roche, le ruisseau l'emporte toujours, non pas par la force mais par la persévérance.

Eléphant du PHP | 190 Messages

02 oct. 2009, 19:19

Re bonsoir.

Je viens de m'appercevoir d'un problème qui est très gênant.

Avec cette regex
$test_chaine = preg_match ('#^[^\#\^\$\(\)\[\]\{\}\+\*\\\|<>&@"²³%µ]{9,50}$#', $chaine);
j'entre 50 "a" dans mon champ, pas de probleme. (50 caractères)
si j'entre des "é" ils comptent pour 2 caractères et donc si j'en écris 26 le preg_match() me bloque.

j'ai essayé avec tout les types de caractères accentués, il comptent tous pour 2 caractères....

une idée ??

Pour info je suis en local sous easyphp.

Mammouth du PHP | 2937 Messages

02 oct. 2009, 19:27

Et en essayant l'option de recherche u, qu'est-ce que ça donne ?
$test_chaine = preg_match ('#^[^\#\^\$\(\)\[\]\{\}\+\*\\\|<>&@"²³%µ]{9,50}$#u', $chaine);

Eléphant du PHP | 190 Messages

02 oct. 2009, 19:39

=D>

C'était si simple ....

Je venais justement de passer mes pages en ISO et ca marchais aussi, mais je préfère resté en utf-8.

Un grand merci a vous tous.

Sinon qu'est ce qui a changé avec ce caractère en plus ? je ne comprend pas tres bien.

:cry: j'ai parlé trop vite: Warning: preg_match() Compilation failed: invalid UTF-8 string at offset 33 in C:\......\.php on line 20.

Mais c'st un bon début.

edit: Ca y'est, 2,3 caractères une peu récalcitrant mais finalement pas tres important. Merci !
Modifié en dernier par Zahnzao le 02 oct. 2009, 20:09, modifié 4 fois.

Mammouth du PHP | 985 Messages

02 oct. 2009, 19:55

http://www.ilu.be/wiki/Aide-memoire_des_regex
u masque UTF-8
Et ne pas confondre avec l'option /U (majuscule)

Je ne connaissais pas non plus cette option :wink:

http://www.php.net/manual/fr/reference. ... ifiers.php
u (PCRE8)
Cette option désactive 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.
[EDIT]
Peux-tu tester cette reg?:
preg_match ('#\w#u', $chaine);
Ou celle-ci qui fera l'opération inverse et donc sera pt moins gourmande en ressources:
preg_match ('#\W#u', $chaine);
Face à la roche, le ruisseau l'emporte toujours, non pas par la force mais par la persévérance.

Eléphant du PHP | 190 Messages

02 oct. 2009, 20:39

Pas mal !
J'ai testé ta regex Dr@ke.

C'est très spécial, ca fait a peu près la meme chose. Très étrange il accepte toute ponctuation mais pas trop de consécutifs. Il prend les crochets et accolades, double et simple quotes. Ca peut être intéressant.

Merci, je vais faire quelques test et je verrai si je la garde ou si je repasse a l'autre.

edit: bah en fait il prend quasi tout les caractères, c'est juste dans leur utilisation qu'ils sont limités. Pourtant la description de cette classe dit: tout les caractères pouvant faire partie d'un mot... bizarre
Modifié en dernier par Zahnzao le 02 oct. 2009, 20:48, modifié 1 fois.