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 Perl Discussion :

Expression Régulière pour remplacer mot non placé entre < et >


Sujet :

Langage Perl

  1. #1
    Nouveau membre du Club
    Homme Profil pro
    Développeur Web
    Inscrit en
    Novembre 2008
    Messages
    49
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : Distribution

    Informations forums :
    Inscription : Novembre 2008
    Messages : 49
    Points : 32
    Points
    32
    Par défaut Expression Régulière pour remplacer mot non placé entre < et >
    Hello,

    Voilà mon problème, je dois scanner un fichier HTML qui contient donc du texte et des balises <..> et effectuer le remplacement d'une chaîne de caractère par cette même chaîne de caractère mais en gras.
    Tout fonctionne correctement mais si par exemple je dois remplacer la chaîne de caractère "le" il va me remplacer tous les "le" qu'il va rencontrer par "le" mais aussi dans les balises comme par exemple <table>

    Donc étant donné que je ne connais pas du tout les expressions régulières je lance une bouteille à la mer pour savoir si quelqu'un peut me dire comme faire ???

  2. #2
    Membre régulier
    Inscrit en
    Janvier 2010
    Messages
    257
    Détails du profil
    Informations forums :
    Inscription : Janvier 2010
    Messages : 257
    Points : 81
    Points
    81
    Par défaut
    Bonjour,
    Ce serait peut être plus facile à comprendre s'il y avait un exemple pour comprendre ton problème

  3. #3
    Nouveau membre du Club
    Homme Profil pro
    Développeur Web
    Inscrit en
    Novembre 2008
    Messages
    49
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : Distribution

    Informations forums :
    Inscription : Novembre 2008
    Messages : 49
    Points : 32
    Points
    32
    Par défaut
    youps

    ma chaine de caractere :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    $chaine = "<i>le chien</i> est très <table><tr><td>petit</td><td>grand</td></tr></table>"
    $search_criteria="le"
    $str_replace="<b>le</b>"
    
    $resultat = str_replace($search_criteria, $str_replace, $chaine)
    
    $resultat = "<i><b>le</b> chien</i> est très <tab<b>le</b>><tr><td>petit</td><td>grand</td></tr></tab<b>le</b>>"
    Alors que moi je voudrais le résultat suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $resultat = "<i><b>le</b> chien</i> est très <table><tr><td>petit</td><td>grand</td></tr></table>"
    J'espère avoir été clair dans mon exemple !

  4. #4
    Membre actif Avatar de brice45
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2005
    Messages
    188
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Mai 2005
    Messages : 188
    Points : 236
    Points
    236
    Par défaut
    Bonjour,

    Le motif que tu recherches est présent entre 2 balises : 1 fermante et une entrante ce qui donne >motif<

    Tu peux essayer cela :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $search_criteria=">le<"
    $str_replace="<b>le</b>"

  5. #5
    Nouveau membre du Club
    Homme Profil pro
    Développeur Web
    Inscrit en
    Novembre 2008
    Messages
    49
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : Distribution

    Informations forums :
    Inscription : Novembre 2008
    Messages : 49
    Points : 32
    Points
    32
    Par défaut
    oui mais si je recherche ">le<" il ne va jamais me remplacer le de ">le chien<" ?
    C'est pour cela que je me disais qu'une expression régulière pourrait peut être solutionner les choses non ?

  6. #6
    Membre actif Avatar de brice45
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2005
    Messages
    188
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Mai 2005
    Messages : 188
    Points : 236
    Points
    236
    Par défaut
    ok je comprends voici un début de code que tu peux améliorer si besoin :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    if ($chaine =~ /\>(.*)\</i)
    	$motif = $1;
    	if ($motif =~ /$search_criteria/i) {
    		$chaine =~ s/$search_criteria/\<b\>$search_criteria\<\/b\>/ig;
    	}

  7. #7
    Membre actif Avatar de brice45
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2005
    Messages
    188
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Mai 2005
    Messages : 188
    Points : 236
    Points
    236
    Par défaut
    avec les accolades c'est mieux
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    if ($chaine =~ /\>(.*)\</i) {
    	$motif = $1;
    	if ($motif =~ /$search_criteria/i) {
    		$chaine =~ s/$search_criteria/\<b\>$search_criteria\<\/b\>/ig;
    	}
    }

  8. #8
    Nouveau membre du Club
    Homme Profil pro
    Développeur Web
    Inscrit en
    Novembre 2008
    Messages
    49
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : Distribution

    Informations forums :
    Inscription : Novembre 2008
    Messages : 49
    Points : 32
    Points
    32
    Par défaut
    merci je vais regarder ça et tester mais peux tu me dire à quoi correspond le $1 ?

  9. #9
    Membre actif Avatar de brice45
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2005
    Messages
    188
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Mai 2005
    Messages : 188
    Points : 236
    Points
    236
    Par défaut
    $1 est une variable qui récupère le contenu entre parenthèses de ton expression régulière

  10. #10
    Rédacteur/Modérateur

    Avatar de Lolo78
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mai 2012
    Messages
    3 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2012
    Messages : 3 612
    Points : 12 256
    Points
    12 256
    Billets dans le blog
    1
    Par défaut
    Je ne pense pas que ça va marcher.

    L'expression:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if ($chaine =~ /\>(.*)\</i) {
    va "gober" tout ce qu'elle peut parce que "/\>(.*)\</" est "gourmand" et essaie donc de faire la reconnaissance maximale.

    Dans la chaîne
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    "<i>le chien</i> est très <table><tr><td>petit</td><td>grand</td></tr></table>"
    cette expression régulière va reconnaître:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    le chien</i> est très <table><tr><td>petit</td><td>grand</td></tr>
    Ce qui n'est pas ce qui est désiré.

    Par ailleurs, il n'est pas utile de mettre un caractère d'échappement devant les '<' et '>'.

    Je partirais plutôt sur une expression régulière comme:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if ($chaine =~  />([^<]*)/i) {
    qui reconnaître un '>" suivi du plus grande nombre possible de caractères autres que '>', et s'arrêtera donc bien à la prochaine balise.

    L'alternative est de choisir une reconnaissance non gourmande.

    La suite du code demande également à être affinée, telle quelle, elle risque de faire de mauvaises substitutions.

  11. #11
    Rédacteur/Modérateur

    Avatar de Lolo78
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mai 2012
    Messages
    3 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2012
    Messages : 3 612
    Points : 12 256
    Points
    12 256
    Billets dans le blog
    1
    Par défaut
    Pour suivre la logique proposée par Brice, j'essaierais quelque chose comme cela:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    if ($chaine =~  />([^<]*)/i) {
         $motif = ">$1<";
         $motif_repl = $motif;
         $motig_repl =~ s/le/<b>le</b>/gi;
         $chaine =~ s/$motif/$motif_repl/ig;
    }
    Il faut ensuite reprendre la substitution à l'endroit où on est arrivé.

  12. #12
    Rédacteur/Modérateur

    Avatar de Lolo78
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mai 2012
    Messages
    3 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2012
    Messages : 3 612
    Points : 12 256
    Points
    12 256
    Billets dans le blog
    1
    Par défaut
    Voici une version corrigée de deux petites fautes de frappe et testée:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    $chaine = "<i>le chien</i> est très le <table><tr><td>petit</td><td>grand</td></tr></table>";
    if ($chaine =~  />([^<]*)/ig) {
         $motif = ">$1<";
         $motif_repl = $motif;
         $motif_repl =~ s/le/<b>le<\/b>/gi;
         $chaine =~ s/$motif/$motif_repl/ig;
    }
    print $chaine;
    ce qui imprime:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <i><b>le</b> chien</i> est très le <table><tr><td>petit</td> <td>grand</td></tr></table>
    Mais cela ne fera la substitution qu'une seule fois. S'il y a plusieurs "le" dans la phrase il faut faire une reconnaissance progressive (dans une boucle while, avec le modificateur "c").

    Ici, j'ai ajouté arbitrairement deux "le" dans la phrase (qui n'a plus de sens, mais c'est juste pour démontrer le fonctionnement). J'ai aussi modifié l'expression régulière pour utiliser un quantificateur non gourmand au lieu d'une classe de caractère : /(>.+?<)/igc.

    J'ai aussi mis un +? au lieu d'un *? comme quantificateur non gourmand pour optimiser (ne pas entrer inutilement dans la boucle pour une reconnaissance de "><").

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    $chaine = "<i>le chien</i> est très le <table><tr><td>petit</td><td>le grand</td></tr></table>";
    while ($chaine =~  /(>.+?<)/igc) {
    	 $motif = $1;
         $motif_repl = $motif;
         $motif_repl =~ s/le/<b>le<\/b>/gi;
         if ($motif ne $motif_repl) {
         	push @mot, $motif;
         	push @mot_repl, $motif_repl;
         }
    }
    while ($motif = pop @mot) {
    	$motif_repl = pop @mot_repl;
    	$chaine =~s/$motif/$motif_repl/gi;
    }
    print $chaine;
    Ce qui me donne:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <i><b>le</b> chien</i> est très <b>le</b> <table><tr><td>petit</td><td><b>le</b> grand</td></tr></table>

  13. #13
    Responsable Perl et Outils

    Avatar de djibril
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    19 820
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 19 820
    Points : 498 771
    Points
    498 771
    Par défaut
    Bonjour à tous,

    Comme je l'ai déjà dit dans une autre discussion pour l'analyse de fichier XML, il en est de même pour les fichiers HTML. Il est absolument important d'utiliser un vrai parseur pour analyser des fichiers HTML (donc balisés). Utiliser des expressions régulières est amusant mais non maintenable car on arrive toujours à des cas tordus.
    Il existe des modules performant sur le CPAN dont l'utilité a été confirmée.

    Faites une recherche sur ce même forum et vous trouverez surement des discussion où je parle de l'utilisation de certains modules.

  14. #14
    Rédacteur/Modérateur

    Avatar de Lolo78
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mai 2012
    Messages
    3 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2012
    Messages : 3 612
    Points : 12 256
    Points
    12 256
    Billets dans le blog
    1
    Par défaut
    Tu as raison, Djibril, l'utilisation des modules ad hoc est bien meilleure, mais il me paraissait de rectifier certaines erreurs courantes sur les expressions régulières.

  15. #15
    Membre actif Avatar de brice45
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2005
    Messages
    188
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Mai 2005
    Messages : 188
    Points : 236
    Points
    236
    Par défaut
    Bien reçu Djibril pour utiliser le CPAN et merci pour tous tes conseils Lolo78

Discussions similaires

  1. [RegEx] Expression régulière pour remplacer des blocs ?
    Par kolbek dans le forum Langage
    Réponses: 1
    Dernier message: 21/04/2011, 17h32
  2. Réponses: 4
    Dernier message: 21/10/2009, 10h17
  3. Réponses: 4
    Dernier message: 14/11/2008, 21h00
  4. Expression régulière pour remplacer une apostrophe
    Par syrius31 dans le forum Langage
    Réponses: 3
    Dernier message: 04/04/2008, 20h34
  5. [RegEx] expression régulière pour remplacer des balises
    Par oceanbigone dans le forum Langage
    Réponses: 5
    Dernier message: 29/05/2007, 18h11

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