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

Web Perl Discussion :

Correction automatique de plus de 700 pages html


Sujet :

Web Perl

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Inscrit en
    Juillet 2006
    Messages
    72
    Détails du profil
    Informations forums :
    Inscription : Juillet 2006
    Messages : 72
    Par défaut Correction automatique de plus de 700 pages html
    Salut à tous. Je suis un débutant en Perl. J'en avais fait un peu y'a quelques années mais j'ai oublié pas mal de trucs. Il se trouve que je suis en ce moment sur un projet un peu athypique: Je ne pourrais faire mes tests qu'au dernier momment. Je suis sous Windows. Voilà pour les présentations.

    Donc voici le code auquel j'ai pensé pour faire ma correction. Après je vous mets mes questions.
    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
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
     
    use File::Find;
     
     
    find(\&wanted,"../../HTML/"); #donc je recherche ce que je veux dans un répertoire HTML qui contient des sous répertoires.
     
    sub wanted #définition de la fonction
    {
      if (/^TS/) #premiere question je dois mettre ça ou bien un $_ eq...  ou bien les 2 vont?
      {
        my $mon_fichier = $_; #on stock le nom du fichier actuel
        open (FILE, $mon_fichier) or die "$!\n"; #fichier actuel ouvert en lecture seule, par contre je met bêtement le $!\n.
     
        open (NEW_FILE, ">temp.html") or die "$!\n"; #fichier temporaire correctif de mon_fichier.
     
        while (<FILE>) { #parcous le fichier ligne par ligne
          my $ligne = $_; 
          #voila mon probleme, je sais pas si ça marche
          if (/toto = \"\#/) # en gros je veux supprimer le #
          {
          $ligne=~s/toto=\"\#/toto=\"/;
          print NEW_FILE $ligne."\n";
          }
          else {
          print NEW_FILE $ligne."\n";
          }
        }
     Close FILE;
     Close NEW_FILE;
    #après je vois pas trop comment remplacer le fichier non corrigé.
    }
    Merci, j'ai déjà pas mal appris en lisant d'autres sujet en rapport. J'espère que j'ai été suffisament clair.

  2. #2
    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
    Tu peux utiliser mon code dans ce thread : http://www.developpez.net/forums/sho...=181760&page=2 .

    Il fait presque exactement ce que tu veux.
    Les problèmes de ton code sont :
    • Veux-tu rechercher dans les sous-répertoire de HTML ? Ton commentaire semble l'indiquer et dans ce cas il te faut utiliser finddepth() à la place de find().
    • Des open() utilisant une syntaxe légèrement dangereuse (qui peut maintenant être remplacée par une syntaxe plus moderne, avec des handles lexicaux et des open à trois arguments)
    • Tu écrases un fichier temp.html sans vérifier s'il existe déjà... (même si tu es persuadé qu'il n'y aura jamais de fichier temp.html dans ce répertoire, prendre des précautions n'est jamais une mauvaise idée).
    • Un code pas forcément très élégant (ni efficace), par exemple tu pourrais plutôt écrire ta boucle :
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
       
      while (my $ligne = <FILE>) {
          $ligne =~ s/toto=\"\#/toto=\"/;
          print NEW_FILE $ligne; 
      }
      J'ai supprimé le "\n" à l'impression parce qu'il y a déjà une fin de ligne dans $ligne (évidemment si tu en étais conscient et que tu voulais rajouter une ligne vide après chaque ligne de ton fichier, il faut le remettre ...).
      Il est inutile de tester puis de remplacer ici, puisque la substitution ne s'effectuera que si le test réussit effectivement, on peut donc se contenter de la substitution. D'ailleurs il y a une erreur dans la regex, révélée par une incohérence entre le test et la substitution : je pense que tu as oublié de prendre en compte les espaces, tu devrais rajouter un "\s*" partout où ils sont susceptibles d'apparaître.
    • Le Close s'écrit close.


    --
    Jedaï

  3. #3
    Membre confirmé

    Inscrit en
    Janvier 2006
    Messages
    188
    Détails du profil
    Informations forums :
    Inscription : Janvier 2006
    Messages : 188
    Par défaut
    connais pas la commande find :s mais à mon avis le fichier à récup se ferait plutot avec un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    sub wanted(){
        my $param=shift;
    }
    sinon, bah... voici un truc qui devrait marcher :
    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
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
     
    my $path='../../HTML/'; # le path absolu serait mieux :s
    opendir(DIR, $path); 
    my @ls=readdir(DIR);
    closedir(DIR);
    chdir($path); # Pour faciliter les open, unlink et rename futur on se met direct dans le dossier ;)
    foreach (@ls){    
        &wanted($_) if (/^TS/); # modif si le fichier commence par TS
    }
    exit 0;
     
    sub wanted(){
        my $file=shift;
     
        open(FILE,$file) or die "$!\n"; #fichier actuel ouvert en lecture seule, par contre je met bêtement le $!\n.
        open (NEW_FILE,">temp.html") or die "$!\n"; #fichier temporaire correctif de mon_fichier.
     
        while (my $ligne=<FILE>) { #parcous le fichier ligne par ligne
    	chomp($ligne); # enlève le retour charriot !
    	$ligne=~s/toto\=\"\#/toto=\"/; # Tu remplaces {toto="#} par {toto="} (Rq : un $ligne=~s/\#// vire direct les #)
    	print NEW_FILE $ligne."\n";
        }
        close(FILE);
        close(NEW_FILE);
     
        # Tu remplaces le fichier
        unlink($file);
        rename('temp.html',$file);
    }
    j'avais pas vu ton post Jedai, ni ton link d'ailleurs :s
    en fait j'ai dit d'la merde..., pas de shift à faire pour la fct du find...

  4. #4
    Membre averti
    Inscrit en
    Juillet 2006
    Messages
    72
    Détails du profil
    Informations forums :
    Inscription : Juillet 2006
    Messages : 72
    Par défaut
    Merci pour vos réponses.
    • Alors oui, dans mon répertoire HTML, il y a plein de sous répertoires et les fichiers qui m'intéressent sont dans ces sous répertoires. Si je me trompe pas la différence entre find et findepth c'est juste que l'un commence du plus haut de la hiérarchie (je sais pas trop comment dire et l'autre le contraire), c'est donc pour une question d'optimisation ou si j'utilisais find, ça marcherait pas?
    • Pour les open, j'ai pas trop compris ce que tu disais. Tu as un lien qui exlique ça?
    • Merci, effectivement j'avais pas pensé que tmp.html pouvait exister. Donc avant de l'ouvrire en écriture, je fais une vérif pour voir s'il existe? Dans ce cas je dois refaire une recherche pour ce fichier aussi?
    • Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      while (my $ligne = <FILE>) {
          $ligne =~ s/toto=\"\#/toto=\"/;
          print NEW_FILE $ligne;
           }
      J'ai oublié de mettre en commentaire que j'hésitais avec cette solution mais j'étais pas sûr que c'était possible. En tout cas ça me plait bien. Autre question, pourquoi tu mets my $ligne= <FILE>? En l'écrivant je viens de me dire que c'est pour définier $ligne.
    • Bien vu encore pour le "\n".
    • Pour les espaces, non c'est à la suite dans le code.
    • merci pour le close au lieu de Close.


    Et donc après pour remplacer le fichier html par le temp, y'a un truc que je visualise pas bien pour le unlink.

    En tout cas, c'est super j'ai l'impression de comprendre un peu mieux le Perl. Merci pour tout.

  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
    • find() est ok, j'ai dû avoir une hallucination quand j'ai lu quelque part qu'il s'arrétait au premier niveau.
    • La forme de open que tu utilises est légèrement dépassée maintenant. Il est recommandé d'utiliser 3 arguments (filehandle, mode (avec éventuellement un filtre), nom du fichier) et en plus d'utiliser un filehandle lexical (déclaré avec my() pour l'occasion) pour éviter d'encombrer l'espace de nom global, ce qui peut réserver de désagréables surprises dans certaines (fort rares) situations. Autre avantage : les filehandles lexicaux sont automatiquement fermés dès qu'on sort de leur portée, ainsi oublier un close a moins de conséquences facheuses. Exemple de la nouvelle syntaxe :
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
       
      open my $in, '<', $infile 
          or die "Couldn't read $infile : $!";
       
      open my $out, '>:encoding(utf-8)', $outfile 
          or die "Couldn't open $outfile in write mode: $!";
       
      while ( <$in> ) {
          #do something with $_
          print {$out} "Exemple\n";
      }
       
      close $in;
    • Regarde mon code, le mieux est d'utiliser un module du CORE pour générer un fichier temporaire dont on est garanti qu'il ne posera pas problème.
    • le my $ligne déclare que $ligne est une variable lexicale dont la portée est limité à la boucle while(), un peu comme si on avait fait :
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      7
       
      {
        my $ligne;
        while( $ligne = <$in> ) {
           ...
        }
      }
    • Pour les espaces dans ta regex : tu es sûr ? Parce que dans ton test tu avais mis un espace par exemple.


    --
    Jedaï

  6. #6
    Membre averti
    Inscrit en
    Juillet 2006
    Messages
    72
    Détails du profil
    Informations forums :
    Inscription : Juillet 2006
    Messages : 72
    Par défaut
    Citation Envoyé par Jedai
    Pour les espaces dans ta regex : tu es sûr ? Parce que dans ton test tu avais mis un espace par exemple.


    --
    Jedaï
    oui oui c'est dans le test qu'il faut pas mettre d'espace. Merci pour tout.

  7. #7
    Membre averti
    Inscrit en
    Juillet 2006
    Messages
    72
    Détails du profil
    Informations forums :
    Inscription : Juillet 2006
    Messages : 72
    Par défaut
    Pas trop eu le temps de bosser dessus. Mais voilà mon code:
    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
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    use strict; # impose de déclarer les variables avant leur utilisation
    use CGI::Carp qw(fatalsToBrowser); #retourne les erreurs dans le navigateur.
    use File::Find; #permet de sélectionner, stocker le fichier, sous répertoire, etc...
    use File::Temp qw(tempfile); #genere un fichier temporaire
     
     
    # on recherche les fichiers dans le répertoire HTML_ie4+
    find(\&wanted, "../../HTML_ie4+/"); 
     
     
    #sous fonction de recherche des fichiers à modifier.
    sub wanted 
    	{
    	if (/^TabS/) { #si le fichier courant commence par TabS, alors 
    		open my $current_file, '<', $File::Find::name
    		or die "Can't read $File::Find::name : $!\n";
     
    		my ($tmp, $tmpname) = tempfile();
    		# les fichiers temporaires sont normalement ouvert en mode binaire, 
    		# dans notre cas nous le voulons plutôt en mode texte
    		binmode( $tmp, ':crlf' );
     
    		while(my $line = <$current_file>) {
    			$line =~ ~s/name=\"\#/name=\"/; #regex qui fait une recherche sur la ligne et remplace s'il trouve la chaine recherchée.
    			print $tmp $line;
    			}	
     
    		close $current_file;
    		close $tmp;
    #------------------------------------------------------------------------------------------------------------------------
    #remplacement de fichier
    		unlink( $File::Find::name )
    		 or die "Can't remove the old file : $!\n";
    		rename( $tmpname, $File::Find::name )
    		 or die "Can't rename the temp file $tmpname : $!\n";
    		}	
    	}
    et j'ai pu le compiler une fois et l'erreur retournée:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    >perl -c -w MODIF.PL
    [Thu Jul 27 09:59:21 2006] MODIF.PL: Can't locate File/Temp.pm in @INC (@INC contains: C:/Perl/lib C:/Perl/site/lib .) at MODIF.PL line 5.
    [Thu Jul 27 09:59:21 2006] MODIF.PL: BEGIN failed--compilation aborted at MODIF.PL line 5.
    Content-type: text/html
     
    <H1>Software error:</H1>
    <PRE>Can't locate File/Temp.pm in @INC (@INC contains: C:/Perl/lib C:/Perl/site/lib .) at MODIF.PL line 5.
    BEGIN failed--compilation aborted at MODIF.PL line 5.
    </PRE>
    <P>
    Enfin quelques questions, j'ai plusieurs fichiers html avec pleins de <br> en fin de fichier. J'aimerais les enlever mais pas pour certains fichier. Comment je peux demander tous les fichiers d'un répertoire sauf ceux commençant par Toto?

    Sinon une autre correction que j'aimerais faire serait de faire plusieurs choses à un même endroit, je m'explique:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    <body onload="poPup=new Array(0,0);" class="Tata"> 
    <!--remplacer par un simple <body>
    mais aussi ajouter 8 lignes avec 7 liens menant vers les autres pages et 1 span pour la page actuelle.

    Merci d'avance pour vos conseils.

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

Discussions similaires

  1. creation automatique de liens dans une page html
    Par arrakis75 dans le forum Balisage (X)HTML et validation W3C
    Réponses: 1
    Dernier message: 22/09/2010, 10h08
  2. scroll automatique ( jscript je suppose) de page html
    Par xini dans le forum Général JavaScript
    Réponses: 2
    Dernier message: 31/12/2006, 19h17
  3. Réponses: 6
    Dernier message: 12/06/2006, 20h03
  4. Appeller 2 pages HTML ou plus
    Par vins25 dans le forum Balisage (X)HTML et validation W3C
    Réponses: 24
    Dernier message: 06/01/2006, 13h01
  5. [INFO]Génération automatique de pages HTML
    Par GreenJay dans le forum API standards et tierces
    Réponses: 6
    Dernier message: 28/09/2005, 16h29

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