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

Java Discussion :

Expression reguliere relativement difficile


Sujet :

Java

  1. #1
    Membre régulier
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2009
    Messages
    194
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2009
    Messages : 194
    Points : 102
    Points
    102
    Par défaut Expression reguliere relativement difficile
    Bonjour a tous,

    Probleme a lafois simple et complexe pour moi. Je me retrouve avec ce genre de String

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    [Recyclage <img src="/Handlers/Image.ashx?size=small&amp;name=2&amp;type=symbol" alt="2" align="absbottom" /><img src="/Handlers/Image.ashx?size=small&amp;name=U&amp;type=symbol" alt="Blue" align="absbottom" /> <i>(<img src="/Handlers/Image.ashx?size=small&amp;name=2&amp;type=symbol" alt="2" align="absbottom" /><img src="/Handlers/Image.ashx?size=small&amp;name=U&amp;type=symbol" alt="Blue" align="absbottom" />, défaussez-vous de cette carte de votre main*: Piochez une carte.)</i>, Quand vous recyclez l'Ensorceleur gemmepaume, tous les sorciers acquièrent le vol jusqu'à la fin du tour.]
    Et je voudrais reussir a faire une expression reguliere qui me permetrait de transformer toutes les balises <img> et leur contenu en une string de ce type :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    "{"+ici_le_contenu_de_l_attribut_alt+"}"
    En gros, je voudrais remplacer mes balise images par la valeur de leurs attribut "alt",cette valeur devant etre entre "{}", mais tout en gardant le reste de la string intact.
    Malheuresement je suis totalement incapable de pondre une regexp pareille....

    Une aide ? une idee ? un conseil*?
    Merci a vous

  2. #2
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Salut,


    Si ton texte est bien formé (pas de > dans le alt, les balises fermé avec des />, etc.) c'est relativement facile.
    Il faut juste maitrisé les reluctant quantifier :
    • "." représente un caractère quelconque.
    • ".*" représente zéro ou plusieurs caractères quelconque... sachant que la plus grande chaine correspondante sera prise en compte.
    • ".*?" représente zéro ou plusieurs caractères quelconque... mais là c'est la plus petite chaine qui sera recherché.


    Exemple, avec ta chaine si tu fais s.replaceAll("<img.*>", "{IMG}") cela va te remplacer tout entre la première balise <img et la fermeture de la dernière balise > et tu obtiendra cecu : "[Recyclage {IMG}, défaussez-vous ...."
    Mais avec les reluctant quantifier tu peux réduire l'impact. Le .*? s'arrêtant dès le premier caractère de fin trouvé. Ainsi s.replaceAll("<img.*?>", "{IMG}") te remplacera bien chacunes des balises <img> indépendamment : "[Recyclage {IMG}{IMG} <i>({IMG}{IMG}, défaussez-vous ...."


    Reste à récupérer le ALT. Perso j'ai pris l'habitude de découper mes regexp pour les rendre plus lisible :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    	String regexp = "<img" // le début de la balise IMG
    			+ "[^>]*?"		// n'importe quoi sauf le tag de fin
    			+ " alt="	// l'attribut alt
    			+ "\""		// une double quote
    			+ "(.*?)"	// n'importe quoi
    						// les parenthèses servent à récupérer la valeur
    						// pour le remplacement (group 1)
    			+ "\""		// une double quote
    			+ "[^>]*?"		// n'importe quoi sauf le tag de fin
    			+ ">";		// la fin du tag
     
    	System.out.println( s.replaceAll(regexp, "$1"));
    Et voilà !



    Tu peux encore avoir un problème si les ALT contiennent un double quote (exemple : alt="text \"quoted\" exemple").
    Pour cela il faut que la quote de fin ne soit pas précédé d'un antislash. Il faut alors utilisé un "lookbehind" qui permet de d'interdire un caractère avant : "(?<!\\\\)\"" (
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    	String regexp = "<img" // le début de la balise IMG
    			+ "[^>]*?"		// n'importe quoi sauf le tag de fin
    			+ " alt="	// l'attribut alt
    			+ "\""		// une double quote
    			+ "(.*?)"	// n'importe quoi
    						// les parenthèses servent à récupérer la valeur
    						// pour le remplacement (group 1)
    			+ "(?<!\\\\)\""	// une double quote, non précédé d'un antislash
    			+ "[^>]*?"		// n'importe quoi sauf le tag de fin
    			+ ">";		// la fin du tag

    Tu peux aussi avoir à gérer des tag alt avec des simples quote (exemple alt='2'), et dans ce cas tu vas devoir utiliser "[\"']" pour la première quote, le tout dans un groupe lié à une back-réréfence (ce qui permettra de prendre en compte le même caractère pour le début et la fin de l'attibut :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    	String regexp = "<img" // le début de la balise IMG
    			+ "[^>]*?"		// n'importe quoi sauf le tag de fin
    			+ " alt="	// l'attribut alt
    			+ "([\"'])"		// une double quote ou une simple quote (group 1)
    			+ "(.*?)"	// n'importe quoi
    						// les parenthèses servent à récupérer la valeur
    						// pour le remplacement (group 2)
    			+ "(?<!\\\\)\\1"	// le même caractère que le group 1, non précédé d'un antislash
    			+ "[^>]*?"		// n'importe quoi sauf le tag de fin
    			+ ">";		// la fin du tag
     
    	// ATTENTION car du coup le numéro de groupe change :
    	System.out.println( s.replaceAll(regexp, "$2"));

    Je pense que c'est à peu près tout.
    Si tu vas utiliser cela souvent je te conseillerais de créer un objet Pattern au lieu d'utiliser replaceAll() de String.
    Ca évitera la création d'un objet Pattern temporaire (ce qui est couteux) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     String s = ".."
     
    String result = s.replaceAll("regexp", "$1")
     
    // Est l'équivalent de :
     
    Pattern p = Pattern.compile("regexp");
    String result = p.matcher(s).replaceAll("$1");
    A noter également que tu pourrais utiliser les flags CASE_INSENSITIVE (pour ignorer la case) ou DOTALL (pour que le "." accepte les retours à la ligne) si tes balises <img> sont sur plusieurs lignes :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Pattern.compile("regexp", Pattern.CASE_INSENSITIVE | Pattern.DOTALL);

    a++

  3. #3
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 565
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 565
    Points : 21 631
    Points
    21 631
    Par défaut
    Ouais enfin bien qu'en général personne ne le fasse, les > dans les attributs sont parfaitement autorisés.

    Alors à moins d'avoir vérifié s'ils sont bien toujours échappés, ou qu'on s'en fiche si ça marche pas dans ces cas-là, moi je dis, les regex sont pas des parseurs et il ne faut pas essayer, un point c'est tout. En plus si le contenu est bien formé, c'est pas les parseurs qui manquent.

  4. #4
    Membre régulier
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2009
    Messages
    194
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2009
    Messages : 194
    Points : 102
    Points
    102
    Par défaut
    Quand je vois ce genre de chose je me dit qu'il faut vraiment que je mette au regexp, c'est tellement puissant (et beau ). Merci beaucoup en tous cas, hier je n'ai plus trop eu le temps, je vais decortiquer ca ajourd'hui. Je pense que je vais en avoir besoin pour plus tard aussi, donc je vais vraiment l'etudier.

    Effectivement je vais en avoir besoin de maniere recurente donc j'essairai d'optimiser le tout.

    Pour ce qui est du parseur html, j'utilise deja jericho, mais sur ce coup la il ne repond pas a mon besoin, et ca va etre beaucoup plus simple de passer une petite regexp que de passer par la creation d'element, de boucle et encore d'autre choses, juste pour tranformer une <img/> en {}. Et normalement la structure du "alt" ne devrait en aucun cas changer donc ca va aller, surtout que je prevois de faire des tests derrieres

    Encore merci, je repasserai pour dire si la regexp a fonctionnee

  5. #5
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par thelvin Voir le message
    Ouais enfin bien qu'en général personne ne le fasse, les > dans les attributs sont parfaitement autorisés.
    Je ne sais pas si c'est réellement autorisé ou si c'est juste supporté par les navigateurs et qu'il faut privilégier le &gt;, mais c'est quelque chose à prendre en compte si on ne maitrise pas la source de données...

    Citation Envoyé par thelvin Voir le message
    moi je dis, les regex sont pas des parseurs et il ne faut pas essayer, un point c'est tout. En plus si le contenu est bien formé, c'est pas les parseurs qui manquent.
    Ben dans ce cas précis il ne s'agit pas de parser un document mais de remplacer une sous-chaine... et les regexp peuvent être adapté dans ce cas.

    Maintenant si l'on doit effectuer des choses plus poussé un parseur peut être plus adapté en effet.


    a++

  6. #6
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 565
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 565
    Points : 21 631
    Points
    21 631
    Par défaut
    Citation Envoyé par adiGuba Voir le message
    Je ne sais pas si c'est réellement autorisé ou si c'est juste supporté par les navigateurs et qu'il faut privilégier le &gt;
    Dans le cas de HTML Live Standards et de HTML5, tout ce qui n'est pas interdit est autorisé, et ce n'est pas interdit. Dans le cas de XML 1.0, le > est explicitement autorisé et le < explicitement interdit.
    Dans le cas de HTML 4.01 et précédents, j'avoue que je ne sais pas. Ce sont des instances de SGML et je manque de moyens de vérifier ce que dit la norme à ce sujet.

  7. #7
    Membre régulier
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2009
    Messages
    194
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2009
    Messages : 194
    Points : 102
    Points
    102
    Par défaut
    Petite parenthèse à votre débat

    La regexp semble fonctionner nickel. J'ai rajouté un petit { et } dans le replaceAll et c'est tout bon.

    Merci beaucoup de votre aide.

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

Discussions similaires

  1. [langage] [Expression][Régulière] motif
    Par Cyspak dans le forum Langage
    Réponses: 4
    Dernier message: 23/09/2003, 14h24
  2. [langage] [debutant] expression reguliere
    Par toto_titi dans le forum Langage
    Réponses: 3
    Dernier message: 01/07/2003, 09h45
  3. Réponses: 2
    Dernier message: 16/06/2003, 15h15
  4. [langage] surement une expression régulière...
    Par armada dans le forum Langage
    Réponses: 5
    Dernier message: 30/05/2003, 17h06
  5. [langage] expression reguliere motif répétitif dans 1 pattern
    Par comme de bien entendu dans le forum Langage
    Réponses: 11
    Dernier message: 09/04/2003, 16h14

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