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 :

pb evaluation regexp


Sujet :

Langage Perl

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    52
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 52
    Par défaut pb evaluation regexp
    Bonjour,
    Je fais mes premiers pas avec Perl et j'ai un petit souci d'evaluation d'une expression reguliere pour extraire du code entre deux balises html.
    Voici le code que je teste :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    sub lirefic(){
        my $fic= $dir.$ligne;
        if(-f $fic){
    	print $fic." : \n";
    	die "ouverture fichier impossible : $!\n" unless open(FIC, $fic);
    	while(<FIC>){
    	    if($_ =~ /<style[^>]+>([^<]+)<\/style>/){
    		print "$_";
    	    }  
    	}
    	close(FIC);
        }
    }
    et voici ce sur quoi j'applique mon expression reguliere :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    <style type="text/css">
    html,body{margin:0;padding:0}
    body{font: 76% arial,sans-serif}
    p{margin:0 10px 10px}
    </style>
    Celui çi ne me renvoir que ceci en resultat d'évaluation ( je suis sur Emacs):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <style type="text/css">^M
    , mais pas le contenu entre les deux balises.
    Mon expression réguliere me semble correcte puisque ça fonctionne avec PHP ( voir çi dessous). J'ai essayé avec les operateurs 'm' et 's' sans succès. Je pense le l'évaluation butte au passage au premier passage à la ligne.

    Qqu'un aurait il une idée ?
    Merci d'avance.
    riccco

    ps un bout de code en PHP qui fonctionne parfaitement sur ce cas:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    function regExtract($f) {
        if(is_readable($f)){ $contenu = file_get_contents($f);}
        preg_match('/<style[^>]+>([^<]+)<\/style>/', $contenu, $match);
        createCssFile($match[1]);   
    }

  2. #2
    Membre chevronné
    Avatar de Schmorgluck
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    371
    Détails du profil
    Informations personnelles :
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Mai 2006
    Messages : 371
    Par défaut
    Le problème, c'est que ton fichier est lu ligne par ligne. Or, ce que cherche ta regex n'est pas sur une seule de ces lignes. Je suis même surpris que tu aies un affichage, vu que ta regex ne peut jamais réussir.

    Deux solutions sont envisageables : lire toutes les lignes de ton fichier, les concaténer avec des retours à la ligne, et enfin utiliser ta regex ; ou utiliser l'opérateur d'étendue ..

    Voici une solution avec la deuxième proposition.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    while(<FIC>){
        if(/<style[^>]+>/../<\/style>/){
            print "$_";
        }  
    }

  3. #3
    Expert confirmé
    Avatar de Jedai
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2003
    Messages
    6 245
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Avril 2003
    Messages : 6 245
    Par défaut
    Citation Envoyé par Schmorgluck
    Deux solutions sont envisageables : lire toutes les lignes de ton fichier, les concaténer avec des retours à la ligne, et enfin utiliser ta regex ; ou utiliser l'opérateur d'étendue ..
    Il y a également la possibilité de lire directement la totalité du fichier.
    De façon idiomatique, ça donne ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    open my($file), '<', $filepath
      or die "$!\n";
    my $content = do { local $/; <$file> };
    close $file;
    my $style = ($content =~ m/ta regex/);
    --
    Jedaï

  4. #4
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    52
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 52
    Par défaut
    Merci Schmorgluck et Jedai pour vos réponses.

    J'ai compris en effet que le pb vient du fait que mon fichier est lu ligne par ligne, or, il est vrai que la fonction PHP que j'utilise place justement le contenu du fichier dans une variable.
    Du coup j'ai utilisé la seconde méthode de Schmorgluck qui fonctionne à merveille. Par contre, j'avoue que je ne comprends pas ce qu'est "l'operateur d'étendue" et ce qui, dans ta syntaxe (solution de la 2eme proposition), fait comprendre ce qu'il faut à l'interpreteur de Perl.

    Je retiens la réponse de Jedai que je mets de côté qd j'aurais un peu plus avancé en Perl car deux choses sont encore bizarre pour moi : l'utilisation de "$/" que je ne connais pas encore, de même que la syntaxe :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    my $content = do { local $/; <$file> };
    pour lire le contenu d'un fichier.

    Merci sinceremment pour vos réponses car c pas si facile de débuter en Perl et c donc très sympa de trouver des âmes charitables pour me faire avancer un peu.

    riccco

  5. #5
    Expert confirmé
    Avatar de Jedai
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2003
    Messages
    6 245
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Avril 2003
    Messages : 6 245
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    my $content = do { local $/; <$file> };
    L'opérateur <> lit par défaut ligne par ligne, mais ce comportement peut être modifié en changeant le contenu de la variable spéciale $/ (séparateur d'enregistrement), par défaut $/ vaut "\n" mais si on lui affecte undef (non-défini), le fichier est lu en entier (on dit qu'il est "slurpé"). local() restreint une modification sur une variable globale à une portée lexicale (un bloc) et "do {}" permet justement de créer une telle portée et renvoie la dernière expression évaluée dans le bloc.
    Ainsi dans le reste du script <> continue à avoir son comportement par défaut, mais on récupère dans $content tout le contenu du fichier.

    Si vous êtes sur un système assez ouvert, une bonne option est d'installer File::Slurp, qui te permettra d'ouvrir, lire, et clore un fichier en une fonction, de façon très efficace.

    --
    Jedaï

  6. #6
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    52
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 52
    Par défaut
    @Jedai, merci pour ces explications très claires de $/ - séparateur d'enregistrement.
    J'essaye actuellement d'installer File::Slurp, mais après un premier essai infructeux, je vais relancer la commande cpan en root...

    Merci beaucoup.

    riccco

  7. #7
    Membre chevronné
    Avatar de Schmorgluck
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    371
    Détails du profil
    Informations personnelles :
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Mai 2006
    Messages : 371
    Par défaut
    Citation Envoyé par riccco Voir le message
    Du coup j'ai utilisé la seconde méthode de Schmorgluck qui fonctionne à merveille. Par contre, j'avoue que je ne comprends pas ce qu'est "l'operateur d'étendue" et ce qui, dans ta syntaxe (solution de la 2eme proposition), fait comprendre ce qu'il faut à l'interpreteur de Perl.
    L'opérateur d'étendue (range operator) est assez délicat à manier en contexte scalaire. En contexte de liste, on l'utilise pour créer une liste d'éléments consécutifs, comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    # on crée une liste de 1 à 10
    my @liste = (1..10);
    Mais en contexte de liste, c'est plus tordu (preuve supplémentaire de l'importance de maîtriser es contextes). Je vais tacher de faire aussi générique que possible : l'expression b1 .. b2, où b1 et b2 sont des expressions interprétables comme valeurs booléennes, a pour valeur faux dans un premier temps, puis sa valeur devient vrai si b1 est vrai, et reste vrai, quelque soit la valeur de b1, tant que b2 est faux.

    Mouais, pas clair. Le plus simple c'est de se le représenter comme un interrupteur, le terme de gauche sert à l'allumer, le terme de droite à l'éteindre.

    L'expression que j'ai utilisée, /<style[^>]+>/../<\/style>/, est donc constituée de deux expressions régulières (testées sur $_ par défaut) reliées par l'opérateur d'étendue. Lorsque la première regex est évaluée à vrai, l'expression prend la valeur vrai jusqu'après que la deuxième regex soit évaluée à vrai (le terme de gauche est évalué à la fin, l'expression renvoie donc vrai une dernière fois, ce qui nous permet d'avoir la dernière ligne).

    Pour être exhaustif, il existe une variante à trois points au lieu de deux, où le deuxième terme n'est pas évalué si le premier est évalué à vrai. Dans l'exemple que tu as donné, cela ne changerait rien, mais si la balise de fermeture était sur la même ligne que la balise d'ouverture, ça ne marcherait pas bien, car la fermeture ne serait pas prise en compte. Cette variante sert dans d'autres circonstances (quand le marqueur de fin est le même que le marqueur de début, par exemple).

    Si j'ai échoué à être compréhensible (ce qui ne m'étonnerait pas) Cet article sera sans doute plus clair.

Discussions similaires

  1. Evaluation d'un nom de fonction
    Par uaz dans le forum Général Python
    Réponses: 1
    Dernier message: 04/08/2004, 11h16
  2. Un outil pour evaluer les dépendances
    Par karbone dans le forum Choisir un environnement de développement
    Réponses: 2
    Dernier message: 30/03/2004, 14h36
  3. [langage] [RegExp] Question d'expression régulière
    Par cloogy dans le forum Langage
    Réponses: 5
    Dernier message: 08/10/2003, 09h29
  4. regexp
    Par mathieu gérard dans le forum ASP
    Réponses: 4
    Dernier message: 02/10/2003, 18h05
  5. Evaluation d’expression
    Par mobisky dans le forum Algorithmes et structures de données
    Réponses: 4
    Dernier message: 09/09/2002, 11h56

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