précédant | suivant | retour | sommaire

Les Expréssions Rationnelles:

aadelmar@wanadoo.fr


Une expression rationnelle est une manière de décrire une chaine de caractères, un modele, sans énumérer tout les caractère qui là compose .
On peut s'en sérvir de plusieurs façon :
  1. - soit en tant que contrôle pour vérifier si la chaine souhaité est présente dans le document. (recherche de correspondance) :     avec m//$youpi =~ m/ma_chaine/;
  2. - soit en remplaçant une chaine par une autre, ce qui permet de restaurer des documents (substitution ) comme dans les exemples suivants : otag1.pl ,     otag2.pl,     html2txt.pl,  html2cvs              avec s///          $ligne =~ s/^<(\w){2,4}.?//;
  3. - soit pour définir les délimiteurs qui séparent les champs de données.  Créer depuis un éclatement plusieurs champs de données.   avec split()    ($nom, $prenom) = split(/ /, $ligne);
L'usage le plus simple des expressions rationnelles est la recherche d'une expression litérale par exemple la recherche dans une page .html de tous les liens vers l'exterieur (http: et ftp:):

 foreach $ligne(@contenu) {
    if  ($ligne =~ /http:| ftp:/) {
        print $ligne;
       }
}

ou implicitement:

while (<>) {
    print if /http:/;
    print if /ftp:/;
    print if /mailto:/;
}

ensuite la substitution avec s/// ou tr qui est un outils too much pour modifier des fichiers quelqu'ils soient.
exemple:
 Vous avez un trouvez un fichier sur le net qui énumére des adresses ou n'importe quoi d'autres que vous aimeriez bien vous servir pour votre base de données perso seulement il est au format HTML (des balises partout) , style:

<TD>abo.wanadoo.fr</TD>
<TD>876</TD>
</TR>
<TR>
<TD>salieri.img.fr</TD>
<TD>228</TD>

etc...     mais c'est pas grave il y a perl.
Vous souhaitez otenir deux fichiers, l'un au format texte avec le nom du domaine et dessous le nombre qui lui est attribué, l'autre un fichier (.cvs) tableau avec element séparés par des virgules, rien de plus facile.
Voici trois exemples:


#!/usr/bin/perl -w
# remd: preparation de liste. adelmar alain

$listea = "lbldom.txt";         # on place les fichiers dans des variables (pas obligé bonne habitudes)
$listeb = "lslblserv.html";

open LSA, $listeaor die "Error: pbOpSrc $!";    # on ouvre le fichier source en lecture.
@contenu= <LSA>;                             # on glisse le contenu à la variable liste @contenu.
close LSA or die "Error pbShutSrc $!";        #on ferme ou on previent

@nwcontenu =<LSB>;             # on prevoit de définir une variable liste pour le résultat.

# pour chaque ligne du contenu {BLOC d'instruction}
foreach $ligne (@contenu) {
     next if length$ligne<= 6        # ote les lignes de 7 caractres au plus.
     $s1 = $ligne;                      # facultatif, place la ligne dans une nouvelle var.
     $s1 =~s/<TD.//;                     # substitue le tag de debut de ligne.
 push @contenu_moins_tagin, $s1;# pousse le contenu dans nlle liste.
}

# on prend le resultat et on recommence avec les tag de fin de ligne.
foreach $s1 (@contenu_moins_tagin) {
 $s2 = $s1;
 $s2 =~ s/()<.?TD.?//;
 print "Je traite la ligne: $s2\n";      # facultatif mais joli
 push @nwcontenu, $s2;
}

# On ouvre le fichier de sortie et on ecrit la liste dessus.
open(LSB, ">$listeb") or die "Error pbOpenCible $!";
print LSB @nwcontenu;
close LSB or die "Error pbShutCible $!";
END;

Les couleurs sont à peu prés celles de gvim lorsqu'il traite du perl (bonnard non?), bon ceci n'est qu'un exemple et en plus pas trés beau, mais ça marche (c'est le premier que j'ai fais pour me faire la main) .
On peut aussi faire plus propre en paufinant (c'est le même mais ne comprend qu'une boucle foreach):

#!/usr/bin/perl -w
# remd: preparation de liste. adelmar alain

$listea = "lbldom.txt";     # on place les fichiers dans des variables (pas obligé bonne habitudes)
$listeb = "lslblserv.html";

open LSA, $listeaor die "Error: pbOpSrc $!"; # on ouvre le fichier source en lecture.
@contenu= <LSA>;                           # on glisse le contenu à la variable liste @contenu.
close LSA or die "Error pbShutSrc $!";      #on ferme ou on previent

@tagot =<LSB>;

foreach $ligne (@contenu) {
     next if length($ligne) <= 6;   # dégage les tags seuls par lignes. (pas terrible !).
     $s1 = $ligne;                # inutile mais bonne habitude pour conserver la ligne pour autre chose.
     $s1 =~ s/<TD.//;             # dégage le tag de début de ligne.
     $s1 =~ s/()<.?TD.//;          # dégage le tag de fin de ligne.
     push @tagot, $s1;             # pousse le tout dans une nouvelle variable liste.
}

open (LSB, ">$listeb") or die "Error pbOpenCible $!";   # ouvre  en lecture-écriture ou previent
print LSB @tagot;                                       # écrit le contenu de @tagot dans le fichier
close LSB or die "Error pbShutCible $!";                # ferme c'est l'heure
END;

Toujours pas terrible bien que cela fonctionne on a en sortie (sur le fichier cible:

abo.wanadoo.fr
886
salegris.img.fr
284

Et voilà la troisiéme version de ce même programme qui fait deux fichiers un ( .txt) et un (.cvs):

#!/usr/bin/perl -w
# remd: preparation de liste. adelmar alain

$listea = "lbldom.txt";        #on place les fichiers dans des variables (pas obligé mais bonne habitudes)
$listeb = "lslblserv.html";   # le source
$listec = "lbldom.csv";       # et le fichier qui resevra la base de données (csv)

open LSA, $listeaor die "Error: pbOpSrc $!"; # on ouvre le fichier source en lecture.
@contenu= <LSA>;                           # on glisse le contenu à la variable liste @contenu.
close LSA or die "Error pbShutSrc $!";       #on ferme ou on previent

@nwcontenu_txt = <LSB>;  # assigner une var list a son handle pour le fichier texte.
@nwcontenu_csv = <LSC>;  # assigner une var list a son handle pour le fichier csv.

foreach $ligne (@contenu) {
     $ligne=~ s/^<(\w){2,3}.?()//;          # ote le tag de debut de ligne.
     $ligne=~ s/()<\/(\w){2,3}.?//;          # ote le tag de fin de ligne.
     next if ($ligne eq "\n");               # dans le cas "<n>" ou "<n><n>".
     push @nwcontenu_txt, $ligne;           # pousse ce qui reste dans liste pour fichier texte
     $ligne_csv = $ligne;                   # defini une nouvelle variable pour file (.csv)
     #***************************on peut faire soit ******** en deux ligne
     chomp $ligne_csv;              # pour oter les sauts de lignes en fin de ligne.
     $ligne_csv = $ligne_csv. ",";  # on ajoute la virgule.
     #************************** soit ************* en une ligne.
     $ligne_csv =~ s/(\n)$/,/;                  # remplasse le saut de ligne par virgule
     # pousse ce qui reste dans une nouvelle var_liste @
     push @nwcontenu_csv, $ligne_csv;
}

open(LSB, ">$listeb") or die "Error pbOpenCible_txt $!";
print LSB@nwcontenu;
close LSB or die "Error pbShutCible_txt$!";
END;

open(LSC, ">$listec") or die "Error pbOpenCible_csv $!";
print LSC@nwcontenu_csv;
close LSC or die "Error pbShutCible_csv$!";

END;

et voilà en sortie on aura deux fichier texte l'un du style :

abo.wanadoo.fr
842
img.lapiequichante.org
123

alors que dans l'autre on aura un fichier (.csv) c'est à dire chargeable dans une base de données car du type séparé par une virgule:

abo.wanadoo.fr,842,img.lechatquimousse.com,136,perso.chevaquissepi.meuh,-12,etc...

Bon bien évidement on peut mieux faire, et je le démontre dessuite dans le prochain exemple ou je nettoi un fichier shtml de la poste,
(videoposte «vos 400 dernieres opérations CCP»  qui au debut me paraissait sans logique. la suite plus loin
(je rappelle que je ne pratique le perl que depuis deux mois et j'arrive à faire tourner des programmes qui me demanderai des années de pratiques avec d'autre langage, perl c'est génial... )



précédant | suivant | retour | sommaire