Précédent   Forum des professionnels en informatique > PHP > Langage > Regex
Regex Forum d'entraide sur les expressions rationnelles PHP. Avant de poster -> FAQ regex, Cours de regex et Sources de regex
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 11/04/2011, 08h04   #1
Membre du Club
 
Inscription : janvier 2010
Messages : 317
Détails du profil
Informations forums :
Inscription : janvier 2010
Messages : 317
Points : 62
Points : 62
Par défaut Assertions et preg_match

Bonjour!

J'ai eu de l'aide pour créer une expression régulière mais je n'arrive pas à comprendre les éléments qui touchent les assertions à partir de mon code:

Je tente de décortiquer le preg_match, si quelqu'un peu m'expliquer la relation entre les éléments :

Code :
1
2
3
4
5
6
7
8
9
10
<?php
$imgUrl = 'a17a5-98uu.Jpg';
echo preg_match('#^[a-z](?=[1-9a-z-]{3,20}[a-z])[0-9a-z]+(?(?=-)-[0-9a-z]+)[a-z]\.jpg$#i',$imgUrl);
?>
<br>
 
décomposé : 
#^[a-z]
(?=[1-9a-z-]{3,20}[a-z])[0-9a-z]+
(?(?=-)-[0-9a-z]+)[a-z]\.jpg$#i
Ce code fonctionne parfaitement mais j'aimerais me le faire expliquer. Ça serait apprécié. Merci.

PS, j'ai fini par comprendre le fonctionnement du forum.
dancom5 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 11/04/2011, 09h26   #2
Membre Expert
 
Homme
Inscription : janvier 2004
Messages : 1 238
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France

Informations professionnelles :
Secteur : Finance

Informations forums :
Inscription : janvier 2004
Messages : 1 238
Points : 1 421
Points : 1 421
#...# sont les caractères qui entourent l'expression régulière. Tu peux utiliser ceux que tu veux, mais en général on utilise des caractères qui ne se trouvent pas dans l'expression.
Historiquement on trouve plus des /, mais on peut aussi utiliser # ou encore ~ qui sont plus lisibles en général

Le "i" final veux dire : insensible a la casse


* ^[a-z]
Le "^" au début veux dire "debut de la ligne". Ca permet de s'assurer qu'il n'y pas de caractère non prévus avant la chaine a vérifier.

[a-z] : tout caractères alpha.

* (?=[1-9a-z-]{3,20}[a-z])[0-9a-z]+
(?=...) est une assertion avant
Ca vérifie que l'expression qui précède ([a-z] ici) est suivie de l'expression entre parenthèse, mais sans la "consommer", a savoir :
[1-9a-z-]{3,20}[a-z] qui veux dire : entre 3 et 20 caractères alphanumériques ou tiret (-) suivi d'un caractère alpha.

[0-9a-z]+ veux dire : 1 ou plusieurs caractères alphanumériques

* (?(?=-)-[0-9a-z]+)[a-z]\.jpg$

(?=-) est une assertion avant comme précédemment, mais utilisée comme ca c'est une condition de sous masque conditionnel :
(?(?=condition)masque)
Donc ici :
Si le caractère qui suit est un tiret (-) alors on vérifie qu'on a le masque :
-[0-9a-z]+, ce qui veux dire "un tiret suivi d'un ou plusieurs caractères alphanumériques"

Enfin, on a :
[a-z]\.jpg$
qui veux dire : un caractère alpha, suivi du caractère point (.) suivi de "jpg".
Le caractère $ veux dire fin de chaine, donc ca interdit qu'il y ait des caractères après.

Doc sur assertions et masques conditionnels :
http://fr.php.net/manual/fr/regexp.r...assertions.php
http://fr.php.net/manual/fr/regexp.r...onditional.php

Pour info je trouve ton expression inutilement compliquée... maintenant j'ai pas forcement envie (ni le temps ^^) de passer 2h a trouver une expression plus simple et qui match exactement la même chose.
__________________
PHP :
Regle n°1 : mysql_query(...), mysql_connect(...) et mysq_select_db(...) doivent EN DEBUG etre suivies de or die(mysql_error()); (mais jamais en production)
Regle n°2 : Mieux encore : mysql_query($requete) or die("$requete<br/>".mysql_error());
Regle n°3 : echo '<pre>';var_dump($var);echo '</pre>'; affiche le contenu et le type d'une variable.
Publiez vos textes de fantasy et de science-fiction sur http://www.cercledefaeries.com/concours/
Fladnag est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 11/04/2011, 10h02   #3
Membre du Club
 
Inscription : janvier 2010
Messages : 317
Détails du profil
Informations forums :
Inscription : janvier 2010
Messages : 317
Points : 62
Points : 62
Par défaut re: Assertions et preg_match

Merci de vous avoir donné la peine de donner des explications.
C'est plus clair mais je dois tester avec d'autres exemple pour
saisir la chose.

Je suis parti du principe avec ça au départ avant de poster ici:

#^[a-z] pour débuter avec un caractère soit de a à z.
[0-9a-z]{3,20} pour avoir en alphanumérique entre 3 et 20.
\.jpg$#i pour finir avec un point et jpg

A partir de ceci, j'avais demandé de l'aide et on m'a sorti des assertions
que je ne connaissais pas.

Je voulais qu'on puisse remplacer un seul caractère par un tiret au besoins.
entre le minimum qui est 3 et le maximum qui est 20. Ma solution de base
permettait de mettre plusieurs tirets alors que j'en voulais un seul et qu'il
soit optionnel. Je voulais aussi pouvoir avec le minimum et le maximum
le fixer à 8 et remplacer un seul caractère par un tiret au besoin.

Comme je comprenait pas les assertions à partir de mon code, j'ai posté
ici.

La notion (?= .... ).... faudrait que je trouve des exemple simple pour bien
comprendre. Ainsi que pour la condition.

Merci pour vos explications encore. Je conserve ce message pour y référer à nouveau plus tard.
dancom5 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 11/04/2011, 10h13   #4
Membre Expert
 
Homme
Inscription : janvier 2004
Messages : 1 238
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France

Informations professionnelles :
Secteur : Finance

Informations forums :
Inscription : janvier 2004
Messages : 1 238
Points : 1 421
Points : 1 421
Ok, donc quelque chose comme ca devrait être plus simple :

#^[a-z][0-9a-z-]{3,20}\.jpg$#i
Ici on peut avoir plusieurs tiret, mais on devrait pouvoir utiliser une seule et unique assertions pour s'assurer qu'il n'y en a qu'un.

Quelque chose comme (non testé) :

#^[a-z](?=[0-9a-z]*-?[0-9a-z]*\.)[0-9a-z-]{3,20}\.jpg$#i

ici la chaine (?=[0-9a-z]*-?[0-9a-z]*\.) ne sert qu'a vérifier qu'on a qu'un seul tiret optionnel (avec ?), n'importe ou avant le point.
Le nombre de caractères est délimité dans l'expression suivante avec {3,20}
__________________
PHP :
Regle n°1 : mysql_query(...), mysql_connect(...) et mysq_select_db(...) doivent EN DEBUG etre suivies de or die(mysql_error()); (mais jamais en production)
Regle n°2 : Mieux encore : mysql_query($requete) or die("$requete<br/>".mysql_error());
Regle n°3 : echo '<pre>';var_dump($var);echo '</pre>'; affiche le contenu et le type d'une variable.
Publiez vos textes de fantasy et de science-fiction sur http://www.cercledefaeries.com/concours/
Fladnag est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 11/04/2011, 10h33   #5
Membre du Club
 
Inscription : janvier 2010
Messages : 317
Détails du profil
Informations forums :
Inscription : janvier 2010
Messages : 317
Points : 62
Points : 62
Par défaut re: preg_match et

Oui, votre solution fonctionne et est plus compréhensible :
j'ai ajouté [a-z] à la fin pour finir le nom du fichier par une lettre.

#^[a-z](?=[0-9a-z]*-?[0-9a-z]*\.)[0-9a-z-]{3,20}[a-z]\.jpg$#i

Je vais essayer de résumer pour l'assertion :

ce qui est vérifier par (?=[0-9a-z]*-?[0-9a-z]*\.)
permet de savoir si j'ai un tiret dans [0-9a-z-]

Si je décidais aussi qu'on puisse remplacer une lettre
ou un chiffre par un _ considérant qu'on a déjà un tiret
Que dois-je faire?

ceci * veux dire au moins un caractère ou plusieurs, ici,
c'est au moins 3 je suppose? surement!

En passant, merci pour l'aide apportée.

Je vais faire d'autres tests en en faisant d'autres.
dancom5 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 11/04/2011, 10h49   #6
Membre du Club
 
Inscription : janvier 2010
Messages : 317
Détails du profil
Informations forums :
Inscription : janvier 2010
Messages : 317
Points : 62
Points : 62
Par défaut Correction

Je viens de découvrir que :
$imgUrl = 'a17a--598a.Jpg';
echo preg_match('#^[a-z](?=[0-9a-z]*-?[0-9a-z]*)[0-9a-z-]{3,20}\.jpg$#i',$imgUrl);
que ça donne vrai même si je mets plusieurs --

C'est pas évident les assertions.
dancom5 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 11/04/2011, 10h54   #7
Membre Expert
 
Homme
Inscription : janvier 2004
Messages : 1 238
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France

Informations professionnelles :
Secteur : Finance

Informations forums :
Inscription : janvier 2004
Messages : 1 238
Points : 1 421
Points : 1 421
Citation:
Envoyé par dancom5 Voir le message
Si je décidais aussi qu'on puisse remplacer une lettre
ou un chiffre par un _ considérant qu'on a déjà un tiret
Que dois-je faire?
Utiliser une classe de caractère :
[-_] veux dire "tiret ou underscore"

#^[a-z](?=[0-9a-z]*[-_]?[0-9a-z]*\.)[0-9a-z-_]{3,20}[a-z]\.jpg$#i

Citation:
Envoyé par dancom5 Voir le message
ceci * veux dire au moins un caractère ou plusieurs, ici,
c'est au moins 3 je suppose? surement!
Non, * veux dire 0 ou plusieurs caractères.
Ici, l'assertion cherche juste a vérifier qu'on a des caractères alphanumériques contenant un et un seul tiret.
Dans la mesure ou l'on ne sait pas combien on a de caractère avant ou après on ne le vérifie pas dans l'assertion, mais uniquement dans la suite de l'expression.

Ce masque matchera avec :
a-aaaa.jpg
aa-aaa.jpg
aaa-aa.jpg
aaaa-a.jpg

Par contre il ne matchera pas avec :
aa-a-a.jpg
a-a-aa.jpg
a--aaa.jpg

(Au passage, si tu ajoutes [a-z] a la fin il faut changer en {2,19} si tu veux avoir entre 3 et 20 caractères)

Si tu veux vérifier qu'il y ait au moins 3 caractères alphanumerique AVANT le tiret tu peux l'indiquer dans ton assertion :
(?=[0-9a-z]{3,}[-_]?[0-9a-z]*\.)
__________________
PHP :
Regle n°1 : mysql_query(...), mysql_connect(...) et mysq_select_db(...) doivent EN DEBUG etre suivies de or die(mysql_error()); (mais jamais en production)
Regle n°2 : Mieux encore : mysql_query($requete) or die("$requete<br/>".mysql_error());
Regle n°3 : echo '<pre>';var_dump($var);echo '</pre>'; affiche le contenu et le type d'une variable.
Publiez vos textes de fantasy et de science-fiction sur http://www.cercledefaeries.com/concours/
Fladnag est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 11/04/2011, 11h01   #8
Membre du Club
 
Inscription : janvier 2010
Messages : 317
Détails du profil
Informations forums :
Inscription : janvier 2010
Messages : 317
Points : 62
Points : 62
Par défaut Merci

M'excuse, je me suis trompé en disant que ça marchais pas.
Je veux tellement essayer et tester que j'ai supprimer \. en
pensant vouloir laisser un caractère avant le point. et jpg.

Merci.. je vais étudier pour aller plus loins. J'ai une base.

dancom5 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 11/04/2011, 14h56   #9
Membre du Club
 
Inscription : janvier 2010
Messages : 317
Détails du profil
Informations forums :
Inscription : janvier 2010
Messages : 317
Points : 62
Points : 62
Salut,

admettons que je voudrais avoir absolument deux :
[-_] veux dire "tiret ou underscore"

d'après mes tests, j'ai essayé ceci :
[-_]{0,2} pour en avoir entre 0 et 2
[-_]{2} pour en avoir absolument 2
[-_]* ou 0 ou plus, mais celui la n'a pas besoin d'assertion.
c'est choses ne fonctionne pas.

un autre cas possible, avoir un underscore, un caractère suivi d'un tiret.

Y'a d'autres possibilités aussi genre ne pas
avoir un tiret un à coté de l'autre ou bien
un tiret suivi d'un underscore.

Le preg_match va être pas mal plus long.

Le but est juste de savoir si j'avais bien
compris mais pour ce que je cherchais
à la base c'est correct.

Merci :-) Mais, je suis satisfait de ce que j'ai appris.
dancom5 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 11/04/2011, 17h30   #10
Membre du Club
 
Inscription : janvier 2010
Messages : 317
Détails du profil
Informations forums :
Inscription : janvier 2010
Messages : 317
Points : 62
Points : 62
J'ai fini par saisir la solution :

Je me permet d'indiquer ici ma solution finale
exemple pour démontrer que j'ai bien compris:

fichier : a_asdfasdf.jpg

#^[a-z](?=[a-z]*[-_]?[a-z]*\.)[a-z-_]*[a-z]\.jpg$#

#^[a-z] commence par une lettre.
(?=[a-z]* doit absolument commencer par au moins une lettre
[-_]? permet la présence d'un tiret ou d'un underscore
[a-z]* afin que le tiret se trouve avant le dernier caractère
\.) la limite du test
[a-z-_]*[a-z]\.jpg$# et fini par une lettre, le . et jpg

A condition que je mettes seulement un underscore ou un tiret.
Ma réplique précédente, m'intéresse toujours mais on peut se baser
sur mon exemple ici. J'ai essayé des choses.

asdf_-asdf.jpg : (?=[a-z]*[_]?[a-z]*[-]? [a-z]*\.)
si je fais -_ à l'inverse, ça marche pas. Alors, je dois mettre plusieurs:
[a-z]*[_]?
[a-z]*[-]? avant et arrière
ou bien mettre [a-z_-] partout.
J'ai compris l'essentiel.

Pour me facilité le travail, j'ai utilisé :
http://lumadis.be/regex/test_regex.php
dancom5 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 11/04/2011, 17h38   #11
Membre Expert
 
Homme
Inscription : janvier 2004
Messages : 1 238
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France

Informations professionnelles :
Secteur : Finance

Informations forums :
Inscription : janvier 2004
Messages : 1 238
Points : 1 421
Points : 1 421
Citation:
Envoyé par dancom5 Voir le message
(?=[a-z]* doit absolument commencer par au moins une lettre
...
[a-z]* afin que le tiret se trouve avant le dernier caractère
Si tu veux avoir au moins une lettre, il faut utiliser + et non *

pas tout compris a la fin, mais n'hesite pas a parcourir la doc php :
http://fr.php.net/manual/fr/regexp.introduction.php
ainsi que tout les liens présents a gauche sur cette partie.

Tu y trouvera ce qu'on peux faire avec des exemples (et des commentaires d'utilisateurs)

C'est pas toujours facile a comprendre, mais très puissant quand on l'a compris ;o)
__________________
PHP :
Regle n°1 : mysql_query(...), mysql_connect(...) et mysq_select_db(...) doivent EN DEBUG etre suivies de or die(mysql_error()); (mais jamais en production)
Regle n°2 : Mieux encore : mysql_query($requete) or die("$requete<br/>".mysql_error());
Regle n°3 : echo '<pre>';var_dump($var);echo '</pre>'; affiche le contenu et le type d'une variable.
Publiez vos textes de fantasy et de science-fiction sur http://www.cercledefaeries.com/concours/
Fladnag est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 11/04/2011, 17h45   #12
Membre du Club
 
Inscription : janvier 2010
Messages : 317
Détails du profil
Informations forums :
Inscription : janvier 2010
Messages : 317
Points : 62
Points : 62
Une chose qui me chicotte:

noms prenoms surnoms
#((?=pre)noms)#

va en prendre aucun

Je voyais ça comme une présence pre et noms.

tandit que :
#((?<!pre)noms)#

va prendre noms et celui de surnoms à noms.
dancom5 est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité Cette discussion est résolue.
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 00h39.


 
 
 
 
Partenaires

Hébergement Web