IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage PHP Discussion :

Assertions et preg_match [RegEx]


Sujet :

Langage PHP

  1. #1
    Membre actif Avatar de dancom5
    Homme Profil pro
    Inscrit en
    Janvier 2010
    Messages
    808
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55

    Informations forums :
    Inscription : Janvier 2010
    Messages : 808
    Points : 241
    Points
    241
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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.

  2. #2
    Membre expérimenté

    Homme Profil pro
    Inscrit en
    Janvier 2004
    Messages
    1 249
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Secteur : Finance

    Informations forums :
    Inscription : Janvier 2004
    Messages : 1 249
    Points : 1 565
    Points
    1 565
    Par défaut
    #...# 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.

  3. #3
    Membre actif Avatar de dancom5
    Homme Profil pro
    Inscrit en
    Janvier 2010
    Messages
    808
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55

    Informations forums :
    Inscription : Janvier 2010
    Messages : 808
    Points : 241
    Points
    241
    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.

  4. #4
    Membre expérimenté

    Homme Profil pro
    Inscrit en
    Janvier 2004
    Messages
    1 249
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Secteur : Finance

    Informations forums :
    Inscription : Janvier 2004
    Messages : 1 249
    Points : 1 565
    Points
    1 565
    Par défaut
    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}

  5. #5
    Membre actif Avatar de dancom5
    Homme Profil pro
    Inscrit en
    Janvier 2010
    Messages
    808
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55

    Informations forums :
    Inscription : Janvier 2010
    Messages : 808
    Points : 241
    Points
    241
    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.

  6. #6
    Membre actif Avatar de dancom5
    Homme Profil pro
    Inscrit en
    Janvier 2010
    Messages
    808
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55

    Informations forums :
    Inscription : Janvier 2010
    Messages : 808
    Points : 241
    Points
    241
    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.

  7. #7
    Membre expérimenté

    Homme Profil pro
    Inscrit en
    Janvier 2004
    Messages
    1 249
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Secteur : Finance

    Informations forums :
    Inscription : Janvier 2004
    Messages : 1 249
    Points : 1 565
    Points
    1 565
    Par défaut
    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]*\.)

  8. #8
    Membre actif Avatar de dancom5
    Homme Profil pro
    Inscrit en
    Janvier 2010
    Messages
    808
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55

    Informations forums :
    Inscription : Janvier 2010
    Messages : 808
    Points : 241
    Points
    241
    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.


  9. #9
    Membre actif Avatar de dancom5
    Homme Profil pro
    Inscrit en
    Janvier 2010
    Messages
    808
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55

    Informations forums :
    Inscription : Janvier 2010
    Messages : 808
    Points : 241
    Points
    241
    Par défaut
    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.

  10. #10
    Membre actif Avatar de dancom5
    Homme Profil pro
    Inscrit en
    Janvier 2010
    Messages
    808
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55

    Informations forums :
    Inscription : Janvier 2010
    Messages : 808
    Points : 241
    Points
    241
    Par défaut
    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

  11. #11
    Membre expérimenté

    Homme Profil pro
    Inscrit en
    Janvier 2004
    Messages
    1 249
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Secteur : Finance

    Informations forums :
    Inscription : Janvier 2004
    Messages : 1 249
    Points : 1 565
    Points
    1 565
    Par défaut
    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)

  12. #12
    Membre actif Avatar de dancom5
    Homme Profil pro
    Inscrit en
    Janvier 2010
    Messages
    808
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55

    Informations forums :
    Inscription : Janvier 2010
    Messages : 808
    Points : 241
    Points
    241
    Par défaut
    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.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [eclipse3.0.1] activer les assertions
    Par MicroPuce dans le forum Eclipse Java
    Réponses: 4
    Dernier message: 15/04/2005, 15h52
  2. Réponses: 3
    Dernier message: 07/12/2004, 22h09
  3. assert ou generer une exception
    Par onap dans le forum C++
    Réponses: 2
    Dernier message: 01/12/2004, 16h49
  4. [Assertions] avec Eclipse
    Par Vorms dans le forum Eclipse Java
    Réponses: 1
    Dernier message: 10/08/2004, 22h54
  5. [Débutant] Utilisation du mot clé ASSERT
    Par analysiz dans le forum Eclipse Java
    Réponses: 2
    Dernier message: 29/07/2004, 11h43

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo