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 :

preg_match dans formulaire pour recupérer les name et value [RegEx]


Sujet :

Langage PHP

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    39
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2005
    Messages : 39
    Par défaut preg_match dans formulaire pour recupérer les name et value
    Bonjour à tous

    Je me permet de vous contacter car j'ai un probleme avec un masque.

    J'ai un string qui contient des input de toutes les sortes
    ce string à cette forme :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    <input name="test" value="bloublou"> 
    blibli 
    <input name='test2' value='bloublou'> 
    blabla 
    <input name="test">
    je désire donc extraire les name et les value conrrespondate mais bien entendu pas les name qui n'ont pas de value correspondante.

    Voici la fonction que j'utilise mais, vous vous en doutez, elle ne fonctionne pas ^^.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    $patern='# [name|value]=["|\']([a-z0-9_./-]+)["|\'] [name|value]=["|\']([a-z0-9_./-]+)["|\']#is'; 
    preg_match ( $patern, $formulairerecupere , $resultatab );

    J'espere que vous allez pouvoir m'aider et vous en remercie d'avance.
    Benoit.

  2. #2
    Membre Expert
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 418
    Par défaut
    Bonjour,



    Horreur !

    Le symbolisme des crochets est destiné à assurer la représentation de ce qui doit être trouvé à UNE position de la chaîne explorée, pas à à assurer un OU entre plusieurs mots de plusieurs lettres. Même si ce qui doit être trouvé à cette position peut être toute une diversité de caractères listés entre les crochets.

    Le symbole des crochets est strictement similaires aux symboles ’\w’, ’\d’ etc qui symbolisent chacun une catégorie de caractères pour UNE position.
    Sauf que ces derniers sont à signification figée: des chiffres pour ’\d’ et pas autre chose, etc.
    Tandis qu’avec les crochets, on dispose de la possibilité de définir sa propre catégorie de caractères pouvant être trouvés à UNE position.

    Pour faire du OU entre mots: les mettre entre parenthèses. Ce faisant on définit un groupe. Pour éviter de définir un groupe, on met ?: après la première parenthèse (ouvrante): (?:the|cafe)




    Avec
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $patern='#<input name=".+?" value=".+?">#'
    la regex ne va réagir que sur les lignes dans lesquelles il y a à la fois name et value.

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    39
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2005
    Messages : 39
    Par défaut
    Merci beaucoup pour cette explication et cette réponse
    Voila donc le patern que j'ai fais et qui fonctionne impecablement :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $patern='#(?:name|value)=(?:"|\').+?(?:"|\') (?:name|value)=(?:"|\').+?(?:"|\')#is';

  4. #4
    Membre Expert
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 418
    Par défaut
    Je t’ai traumatisé avec ma petite explication sur les crochets....
    Il faut utiliser ce symbolisme quand on peut, c’est à dire pour représenter des OU entre des caractèes uniques. On ne passe à ( | ) ou (?: | ) que lorsqu’il y a des OU qui impliquent au moins un mot de plus de 1 lettre.
    Mais dans ton cas
    (?:"|\') c’est ["|\']




    D’autre part, il y a quelque chose qui ne va pas.
    Si name précède toujours value (quand il y a value) dans toutes les lignes, comme tend à le faire conclure la courte chaîne que tu as donnée comme exemple, alors la RE que tu as écrite est une complication qui va fatiguer inutilement le moteur de regex. Il est bien mieux pour lui d’avoir
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $patern = '#name=["|\'].+?["|\']value=["|\'].+?["|\']#is';



    Autre chose: si 'name' est toujours précédé de ’<input ’ , il ne faut pas se priver de le mettre dans la RE. Voici pourquoi:

    quand le moteur de regex cherche un motif symbolisé par la RE '#name=["|\']...etc’ , il examine chaque lettre de la chaîne explorée l’une après l’autre et teste s’il s’agit de ’n’ ou non. En fait , je ne sais pas EXACTEMENT comment travaille le moteur de regex. Il se peut qu’il examine 2 lettres à la fois, ou 3 lettres, et fasse des sauts d’un groupe de 3 lettre au groupe de 3 lettres suivant. Les moteurs de regex sont optimisés. Le détail, je l’ignore, mais dans le principe c’est ce que j’ai compris de diverses lectures sur les regex.

    Je continue donc sur l’hypothèse que le moteur teste chaque lettre l’une après l’autre. Que se passe-t-il ?
    Il examine ’<’ : non ce n’est pas ’n’
    Il examine ’i’ : ce n’est pas ’n’
    Il examine ’n’ : ah c’est bon -> il examine si la suite correspond à ’a’ ou ’am’ ou ’ame’ ou ’ame=’... je ne sais pas exactement. En tous cas, il s’arrrète sur ’n’ , examine la suite, constate que ça ne matche pas... et recommence d’avancer:
    Il examine ’p’ : ce n’est pas ’n’
    etc.....

    Donc le moteur de regex va passer du temps à examiner ’<input ’ avant de tomber sur ’name=..etc’ qui va matcher. Ce temps est une perte de temps si on sait qu’il y a toujours ’<input ’ devant ’name=’. En écrivant les caractères fixes ’<input ’ en tête de la RE , c’est mieux pour le moteur, ça rend son activité plus efficace et plus rapide. Moins il y a de symboles polysémiques (= représentant une diversité de caractères et non pas un seul fixé) dans une RE, plus c’est simple à chercher pour le moteur de regex.





    Encore autre chose: comment récupères tu les chaînes qui suivent name et value ?
    Il faut les attraper avec de parenthèses:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $patern = '#<input name=["|\'](.+?)["|\']value=["|\'](.+?)["|\']#is';
    L’instruction preg_match ( $patern, $formulairerecupere , $resultatab ); créera un array $resultatab dans lequel $resultatab[1] sera la valeur name et $resultatab[2] sera la valeur value.





    Dans la RE il y a des points dans les deux portions (.+?)
    Les valeurs de name et value sont elles susceptibles de s’étaler sur plusieurs lignes ? C’est à dire est il possible qu’il y ait ’\n’ au sein d’une valeur name ou d’une valeur value ?
    Par exemple est il possible que
    <input name="arctique
    et antarctique" value="bloublou">
    blibli
    ce qui correspond à
    “<input name="arctique\net antarctique" value="bloublou">\nblibli“


    Si ce n’est pas le cas, l’option s ne sert à rien puisqu’elle a pour utilité de faire matcher le métacarctère point avec les fins de ligne.

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    39
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2005
    Messages : 39
    Par défaut
    Merci pour cette belle explication
    C'est plus que gentil.

    Voila ce que je fais donc maintenant :
    $formulairerecupere contient le formulaire

    je nétoie le formulaire comme ca :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $patern='#((?:id|class|size|type|style|maxlength)=[?:"|\'][a-z0-9_./-]+[?:"|\'])#is';
          $formulairerecupere=preg_replace($patern," ", $formulairerecupere);
    Ensuite je cherche les lignes.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $patern='#<input (?:name|value)=[?:"|\'].+?[?:"|\'] (?:name|value)+=[?:"|\'].+?[?:"|\'] >#is';
          preg_match_all ( $patern,  $formulairerecupere  , $resultatab );
    Ensuite, je boucle sur $resultatab et sur les sous tableau pour récuperer les valeurs.

    Par contre j'ai un soucis avec les input qui n'ont qu'un nom.

    Comment puis je modifier
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $patern='#<input (?:name|value)=[?:"|\'].+?[?:"|\'] (?:name|value)+=[?:"|\'].+?[?:"|\'] >#is';
    pour que le value soit optionel?
    (
    je demande car si j'ai par exemple :
    <input name="test"><input name="autre" value="autrevaleur">
    et bien je recois la correspondance "test a+autrevaleur' car il cherche le value d'apres ^^.
    )

    Encore merci pour tout, je met ce topic dans mes favoris, ca m'aider bien

    Ben.

  6. #6
    Membre Expert
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 418
    Par défaut
    L’expression
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $patern='#<input (?:name|value)=[?:"|\'].+?[?:"|\'] (?:name|value)+=[?:"|\'].+?[?:"|\'] >#is';
    comporte un blanc avant >#is’; qui rend cette RE inapte à matcher avec les chaînes que tu présentes comme ses objectifs.

    Bon, je suppose que c’est une erreur de copier-coller et qu’en fait tu as bien exécuté des codes avec la RE
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $patern='#<input (?:name|value)=[?:"|\'].+?[?:"|\'] (?:name|value)+=[?:"|\'].+?[?:"|\']>#is';
    qui, elle, ma[rt]che.



    Soit dit en passant: mes excuses pour la RE écrite dans mon précédent message: elle était fausse; il y manquait un blanc entre name=["|\'].+?["|\'] et value=["|\'].+?["|\']







    Ta RE marche donc mais produit effectivement un souci:
    sur ch = '<input name="test"><input name="autre" value="autrevaleur">'
    elle matche avec la totalité de cette chaîne et non pas seulement avec ’<input name="autre" value="autrevaleur">' comme souhaité.

    Pourquoi ?

    Ce qu’il faut comprendre, c’est qu’un moteur de regex fait des essais tant qu’il le peut pour trouver un matching. Quand l’algorithme qui régit le moteur d’une regex particulière ( regex = objet obtenu par compilation d’une RE=regular expression ) a épuisé toutes les possibilités essayables , le résultat est “Rien trouvé“.

    Mais avant cette extrémité, le moteur de regex se démène pour trouver un matching.

    Dans le cas présent, la portion <input (?:name|value)=[?:"|\'] de la RE matche avec ’<input name="’

    .+? doit ensuite grignoter des caractères jusqu’à ce qu’il rencontre ..... la suite.

    Il grignote donc ’test’ et tombe sur '"' . La suite spécifiée par la RE doit bien commencer par un '"' . Mais elle ne se limite pas à ce seul caractère, il faut en fait que toute la suite du ’“’ rencontré matche avec la suite ><input name="autre" value="autrevaleur"> de la RE.

    Or ce n’est pas le cas: dans ch, le '"'est suivi de ’>’ et non pas du blanc indiqué par la RE.

    Donc le moteur de regex laisse tomber cet essai et recommence à chercher un caractère '"'

    Il tombe sur '"' devant 'autre' , qui ne va pas parce qu’il est suivi de ’a’

    Il tombe ensuite sur le '"' suivant dont la suite est aussi conforme à la RE jusqu’au bout.

    Pour confirmer cette interprétation, il suffit de mettre .+? entre parenthèses => la capture ainsi définie attrape 'test"><input name="autre'





    D’ailleurs, pourquoi n’as tu pas mis entre parenthèses les deux portions .+? qui doivent matcher avec ce dont tu dis dans le premier message que c’est ce que tu veux extraire ?
    J’en ai bien parlé pourtant...
    Encore autre chose: comment récupères tu les chaînes qui suivent name et value ?
    Il faut les attraper avec des parenthèses:




    Le problème consiste en ce qu’en fonction de la chaîne explorée, il est susceptible d’y avoir des cas où le motif .+? va plus loin que le premier [“|\’] rencontré, malgré le fait que ? limite le caractère glouton du quantificateur +.

    ? fait en effet stopper le moteur de regex devant la première chaîne qui matche avec la suite de .+? , et non pas le premier caractère que doit matcher cette suite.

    La seule solution radicale pour faire stopper devant le premier caractère [“|\’] rencontré est d’exclure " et ' de la chaîne qui doit matcher devant le premier caractère de la suite voulue.

    Ceci dit, est-ce que tu voudrais bien répondre ? Y a-t-il ou non possibilité de rencontrer value avant name dans une balise ? Si cette possibilité existe il faut prendre la RE
    <input name=["|\']([^"\']+)["|\'] value=["|\']([^"\']+)["|\']

    Sinon il faut
    <input (?:name|value)=["|\']([^"\']+)["|\'] (?:name|value)=["|\']([^"\']+)["|\']





    Nota bene:

    Il n’y a que les parenthèses qui définissent des groupes capturant. Les deux caractères ?: successifs n’ont donc leur aptitude à rendre non capturant un groupe qu’après une parenthèse gauche.

    [?:"|\'] définit un ensemble de caractères possibles pour une position:
    '?'
    ':'
    '"'
    "'"

  7. #7
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    39
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2005
    Messages : 39
    Par défaut
    Et bien, je ne sais pas comment te remercie
    Ton aide m'a ete plus que précieuse pour la réalisation de mon petit outil.
    Je garde ce topic en favoris et ca m'aidera bcp dans l'avenir.
    Encore merci, bonne soirée.
    Benoit.

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

Discussions similaires

  1. [AC-2010] Bouton dans formulaire pour ouvrir les importations enregistrées
    Par borisp dans le forum VBA Access
    Réponses: 0
    Dernier message: 21/07/2014, 12h36
  2. [LibreOffice][Tableur] Pb dans macro pour compter les couleurs
    Par fransix dans le forum OpenOffice & LibreOffice
    Réponses: 1
    Dernier message: 27/06/2013, 19h12
  3. Réponses: 3
    Dernier message: 27/08/2010, 13h58
  4. Réponses: 1
    Dernier message: 18/12/2008, 22h31
  5. [MySQL] erreur sql dans formulaire pour inscription membre
    Par kate59 dans le forum PHP & Base de données
    Réponses: 5
    Dernier message: 29/02/2008, 13h08

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