2010-03-31 10 views
0

J'ai un problème intéressant. J'ai écrit le script Perl suivant à boucle récursive dans un répertoire et dans tous html fichiers pour img/script/a balises, procédez comme suit:Modifier les liens hypertexte dans les balises imbriquées qui ne sont pas sur des lignes distinctes

  • Convertir l'URL complète en minuscules
  • Remplacer les espaces et% 20 avec underscores

Le script fonctionne très bien sauf si une balise d'image est enveloppée avec une balise d'ancrage. Existe-t-il un moyen de modifier le script actuel pour qu'il soit également capable de manipuler les liens pour les balises imbriquées qui ne sont pas sur des lignes séparées? Fondamentalement, si j'ai <a href="..."><img src="..."></a> le script ne changera que le lien dans la balise d'ancrage, mais ignorer la balise img.


#!/usr/bin/perl 

use File::Find; 

$input="/var/www/tecnew/"; 

sub process { 
     if (-T and m/.+\.(htm|html)/i) { 
       #print "htm/html: $_\n"; 

       open(FILE,"+<$_") or die "couldn't open file $!\n"; 
       $out = ''; 
       while(<FILE>) { 
         $cur_line = $_; 
         if($cur_line =~ m/<a.*>/i) { 
           print "cur_line (unaltered) $cur_line\n"; 
           $cur_line =~ /(^.* href=\")(.+?)(\".*$)/i; 
           $beg = $1; 
           $link = html_clean($2); 
           $end = $3; 
           $cur_line = $beg.$link.$end; 
           print "cur_line (altered) $cur_line\n"; 

         } 
         if($cur_line =~ m/(<img.*>|<script.*>)/i) { 
           print "cur_line (unaltered) $cur_line\n"; 
           $cur_line =~ /(^.* src=\")(.+?)(\".*$)/i; 
           $beg = $1; 
           $link = html_clean($2); 
           $end = $3; 
           $cur_line = $beg.$link.$end; 
           print "cur_line (altered) $cur_line\n"; 
         } 
         $out .= $cur_line; 

       } 
       seek(FILE, 0, 0) or die "can't seek to start of file: $!"; 
       print FILE $out or die "can't print to file: $1"; 
       truncate(FILE, tell(FILE)) or die "can't truncate file: $!"; 
       close(FILE) or die "can't close file: $!"; 
     } } find(\&process, $input); 

sub html_clean { 
     my($input_string) = @_; 
     $input_string = lc($input_string); 
     $input_string =~ s/%20|\s/_/g; 
     return $input_string; 
} 
+0

Je vois un autre problème dans votre script: que se passe-t-il si les attributs de tag sont situés sur plusieurs lignes?

Répondre

3
+0

Ou si vous avez une validation HTML, utilisez XML :: LibXML. – reinierpost

+1

@reinierpost La validation de 'HTML' n'a pas besoin d'être' XML'. Utilisez un analyseur 'HTML' pour analyser' HTML'. –

+0

J'ai fini par utiliser HTML :: TokeParser :: Simple. Il est beaucoup plus propre et plus facile de manipuler les éléments HTML. Merci Ceci est un site génial. – user305801

0

je serais vraiment suggérer pour obtenir tout le texte HTML dans la mémoire et effectuer une recherche multiligne et le remplacer par une étiquette toute correspondance RE:

text =~ s/(<a[^>]+href=")([^"]+)("[^>]+>.*?</a>)/$1 . &html_clean($2) . $3/ge 
Questions connexes