Bonus Perl !

Notre script bash achevé, nous avons décidé de nous lancer dans une nouvelle (més)aventure : concevoir un traitement similaire en perl. Les scripts de base en main, nous avons alors tenté de reproduire, non sans mal, les différents processus que nous avions mis en place sous bash.
Le résultat n'est pas tout à fait à la hauteur de nos attentes, mais nous attendons avec impatience le prochain projet pour nous améliorer !
Vous trouverez ci-dessous une petite description, non exhaustive, de quelques notions liées à la syntaxe de Perl et aux commandes utilisées dans le script.

Embûches :

Nous avons connu plusieurs difficultés lors de la réalisation de ce script :
  • Bonus "$dico" : l’intégration de cette notion, qui permettait dans le script bash d’informer l’utilisateur de l’extraction d’un mauvais sens dans le contenu textuel, n’a pas été aussi simple que nous le pensions. En effet, il ne nous a pas été possible de l’incorporer au mieux malgré de nombreuses tentatives.
    Nous nous sommes alors rabattus sur une solution plutôt ‘basique’, la seule qui voulait bien fonctionner sans faire trop d’erreurs : une condition ‘if’ était placée hors de la boucle 'while' afin que le programme informe l’utilisateur (en ajoutant une ligne à la fin du fichier contexte) s’il avait rencontré le motif non désiré dans le contexte déjà créé (code de la solution de secours et exemple de résultat).

    Néanmoins, cette solution basique n’a pas été suffisante : pour des raisons qui nous échappent, le traitement bloquait pour certaines URLs et le programme ne pouvait donc poursuivre le parcours et le traitement des urls suivantes.
    Finalement, n’ayant aucune autre solution en vue, nous nous sommes vus contraints d’abandonner cette idée… c’est bien dommage.

  • URLs en chinois : nous avons été dans l'impossibilité de les traiter car la commande get(url) n'aspirait pas ces pages, bien que les procédures étaient sensées encoder en utf-8 et que nous ayons essayé en sus d'encoder en utf-8 les entrées et les sorties de fichiers (avec la commande open(fichier,">:encoding(UTF-8)",$fichier) ou encore decode ("utf-8", $URL)...).
    Après maintes tentatives, toutes autant inefficaces les unes que les autres, nous nous sommes résolus (encore une fois!) à abandonner leur traitement.

  • ______________________________________________________________

    Perl : Kézako ?

    Perl (Practical Extraction and Report Language) est un langage de programmation créé par Larry Wall en 1987 pour la manipulation automatique de textes (comme son nom l’indique, même si l’acronyme a été forgé à postériori). C’est un langage qui, comme bash, est interprété et pré-compilé lors de son exécution.
    Perl présente plusieurs caractéristiques :
  • ce langage est souple, simple mais puissant : il se veut pratique et facile à utiliser, plutôt qu’élégant et compact ;
  • il combine plusieurs fonctionnalités issues de C, sed, awk et sh ;
  • il est optimisé pour l’extraction d’informations de fichiers texte et la génération de rapports, traitements qui étaient parfois "limités" avant sa création, mais il est également utilisé dans une large gamme de tâches (administration système, développement web, programmation réseau, création d’interfaces graphiques, etc.).

  • Pour en savoir plus...

    NB :

    Il existe toujours plusieurs façons de réaliser une même opération, d’où l’une des devises « Perl : la tronçonneuse suisse des langages de programmation (TIMTOWTDI) » qui lui est associée.

    _______________________

    Les variables en Perl


    Il existe trois types de variables en perl dont les deux suivantes (utilisées dans le script), qui peuvent prendre comme valeur différents types de données :
  • les variables scalaires

    $cdc = "chainedecaractères"
    $nb = nombre
    $var = $variable

  • les listes (ou tableaux)

    @nom_tab=('toto',"$var",3)

  • ! Attention ! Une chaîne de caractères encadrée par des apostrophes s’affiche telle qu’elle a été saisie (elle n'est pas interprétée par Perl, contrairement au contenu des guillemets doubles).
    $var = "toto";
    print
    "$var\n"; # Affiche : toto
    print
    '$var\n'; # Affiche : $var\n

    Remarque sur la portée des variables : une variable perl est par défaut 'globale', visible dans l'ensemble du code (c'est-à-dire accessible telle quelle, avec la même valeur assignée une seule fois).
    Lorsque l'on veut restreindre la visibilité d'une variable à un bloc d'instructions (et rendre ainsi la variable 'locale'), on utilise la fonction
    my
    lors de l'assignation d'une valeur à la variable dans ce même bloc (pour cela, on utilise la directive "
    use
    locale;" en début de script).
    On peut par la suite modifier sa valeur sans utiliser
    my
    (au sein du bloc d'instructions).

    _________
    Il existe également des variables par défaut, très pratiques du point de vue de la concision et de la lisibilité du script :
  • $_ : variable contenant la valeur courante (par exemple, si on lit une un fichier ligne par ligne à l'aide de la boucle
    while
    , $_ prendra comme valeur de la ligne courante).
    Elle peut également s'utiliser de manière implicite (sans être mentionnée)

  • @ARGV : variable contenant la liste des arguments passés sur la ligne de commande au script en cours d'exécution.
    Comme $_, elle peut s'utiliser de manière implicite

  • @_ : variable contenant les arguments passés au sous-programme en cours (les routines
    sub
    ).

  • $@ : variable contenant le message d'erreur fatale du dernier
    eval
    () qui a été exécuté.
    Si $@ est vide, cela signifie que le dernier
    eval
    () a été évalué et exécuté correctement.

  • $! : variable contenant le message d'erreur fatale du dernier
    die
    qui a été exécuté.
    (vide lorsque l'instruction précédant
    die
    s'est déroulée correctement).

  • $1, $2, ... : ces variables permettent de faire des références arrières (mémorisation) sur le contenu d'une expression régulière.
    Exemple : dans $motif=~ (directions?|\\w*-ways?|ways?), $1 a pour valeur "direction", "directions", "-way", "-ways", "way" ou "ways".

  • $`, $& et $': ces variables sont utilisées pour définir ce qu'il y a autour du motif reconnu par une expression rationnelle.
    $` aura pour valeur la partie de la chaîne qui est avant ce qui a été reconnu,
    $& aura pour valeur la partie de la chaîne qui a été reconnue,
    et $' aura pour valeur la partie de la chaîne qui est après ce qui a été reconnu.

  • _______________________

    Quelques opérateurs


    =
    : permet l'assignation d'une valeur à une variable
    .
    : permet la concaténation de chaînes

    Remarque : pour la concaténation des valeurs que peut prendre une même variable, on utilise $var
    .=
    $var .

  • Opérateurs de comparaison numérique
    ==
    : comparateur d'égalité
    !=
    : comparateur d'inégalité

  • Opérateurs de comparaison de chaînes
    eq
    : comparateur d'égalité
    ne
    : comparateur d'inégalité

  • Opérateurs booléens
    &&
    ou
    AND
    : signifie "et"
    ||
    ou
    OR
    : signifie "ou"
    !
    ou
    NOT
    : négation

  • _______________________

    Quelques structures de contrôle


  • if
    :
    Comme tout langage de programmation, Perl possède une structure conditionnelle.
    Elle permet de conditionner l'exécution d'instructions : si la condition est vérifiée, le bloc d'instructions (els)if sera exécuté ; sinon, la programme passe au bloc d'instructions sous else.
    Pour lier plusieurs conditions, on utilise les opérateurs booléens.

    Syntaxe de la commande
      if
      ( condition(s) ) { liste d'instruction(s); }
      elsif
      ( autre(s) condition(s) ) { liste d'instruction(s); }
      else
      { liste d'instruction(s); }


    Remarque :
    Il existe également une version négative du
    if
    :
      if
      ( !condition(s) ) =>
      unless
      ( condition(s) ) { instruction(s) }

  • foreach
    :
    Cette boucle permet de parcourir une table. A chaque tour de boucle, l'élément de la liste est affecté à la variable $var.

    Syntaxe de la commande
      foreach
      $élément (@liste) { liste d'instructions; }

  • while
    :
    Cette boucle permet d'appliquer des instructions tant que la/les condition(s) est/sont respectée(s), c’est-à-dire tant qu’elle(s) retourne(nt) la valeur « Vrai ».

    Syntaxe de la commande
      while
      ( condition(s) ) { liste d'instruction(s); }

  • _______________________

    Quelques commandes


    NB :

    il peut exister d'autres syntaxes pour une même commande, et si une variable n'est pas précisée dans une instruction, cette dernière s'applique générallement à $_.

  • close
    ( FIC ) :
    ferme le fichier correspondant au descripteur (ici, FIC, c'est-à-dire le nom donné au fichier lors de son ouverture pour pouvoir manipuler son contenu). Pour les dossiers, on utilisera
    closedir
    ( DOS ).

  • decode
    ( $var ) :
    Cette commande, qui provient du module Encode, permet le décodage d'une chaîne de caractères.

  • decode_entities
    ( $cdc ) :
    Cette commande, qui provient du module HTML::Entities, permet le remplacement des entités HTML dans une chaîne de caractères par leur point de code en ISO-8859-1 correspondant.

  • defined
    ( $var ) :
    Cette commande retourne une valeur positive si la valeur de la variable (ou la fonction &funct) est définie.

  • die
    "commentaire" :
    utilisée comme cas échéant avec une autre commande, elle permet de stopper l'exécution du script si l'autre commande a rencontré une erreur (ou de passer à la suite si une partie du code ne nécessite pas le résultat de la commande).
    Il est préférable de commenter la fonction pour que l'utilisateur sache quelle commande a rencontré des problèmes, et y indiquer $! permet d'afficher les erreurs.

  • eval
    { liste d'instruction(s); }:
    intercepte les exceptions et gère les erreurs qui en sont liées.

  • exit
    :
    permet de mettre fin au programme.

  • get
    ( $url ) :
    Cette commande provient du module LWP::Simple et permet d'aspirer le contenu des pages Web en le stockant sur le disque local (à la manière de
    wget
    sous bash).

  • length
    ( $var ) :
    retourne la longueur en caractères de la valeur de $var.

  • mkpath
    "chemin" :
    Cette commande, qui provient du module File::Path, permet de créer une arborescence par récursivité (il n'est plus nécessaire de préciser chaque chemin pour chaque sous-dossier, comme avec la commande
    mkdir
    servant sous Perl et sous bash).

    Exemple :
      Syntaxe de mkpath

  • my
    $var :
    permet de déclarer les variables locales.

  • next
    :
    permet de passer à la prochaine itération de la boucle.

  • open
    (FIC,$fichier) :
    permet d'ouvrir les fichiers (en écriture "<", en écriture avec concaténation "<<" en lecture ">"). $fichier contient le chemin du fichier et associe son contenu à FIC (descripteur).
    Pour les dossiers, on utilisera
    opendir
    (DOS,$dossier), dont le contenu sera lu à l'aide de la commande
    readdir
    (DOS).

  • print
    (FIC) "contenu" :
    Cette commande permet d'afficher le contenu se trouvant entre guillemets (dans un fichier en sortie lorsque l'on utilise son descripteur ; sinon dans l'invite de commande).

  • return
    $var :
    retourne la valeur résultante d'une fonction (on parle de fonction, et non de procédure, lorsque cette dernière renvoie une valeur).

  • rmtree
    "chemin" :
    Cette commande, qui provient du module File::Path, permet de supprimer une arborescence de dossiers en ne précisant seulement le chemin du dossier supérieur.

  • sub
    nom_fonction { instruction(s) } :
    Cette commande permet d'introduire des fonctions (ou procédures, sous-routines), qui sont des blocs de code appelés dans un autre endroit du script (pour des raisons de lisibilité, on les place générallement à la fin du script).

  • substr
    ( $cdc, i, j, $cdc_de_remplacement ) :
    extrait une sous-chaîne de caractères d'une chaîne de caractères.

    Cette commande prend en compte 4 paramètres (les deux derniers sont facultatifs) :
    - la chaîne de laquelle il faut extraire la sous-chaîne,
    - la position du premier caractère de la sous-chaîne (! attention ! la numérotation commence à zéro),
    - le nombre de caractères que doit comprendre la sous-chaîne,
    - une chaîne de caractères de remplacement.

  • use
    nom::module :
    Cette commande permet de déclarer et d'importer les modules utilisés dans le script.

  • -X
    DESCRIPTEUR ou $fichier :
    Cette commande sert à tester si un fichier respecte certaines propriétés (selon la lettre utilisée), et retourne en général la valeur 1 ou nulle.

    -X
    peut prendre l'une des formes suivantes :

    -f
    : Le fichier est un fichier normal.
    -d
    : Le fichier est un répertoire.
    -z
    : Le fichier a une taille nulle.
    -s
    : Le fichier n'a pas une taille nulle (retourne sa taille en octets).

  • Pour plus de précisions sur le fonctionnement des commandes...
    ______________________________________________________________

    Script

    Cliquer ici pour visualiser le script.
    ______________________________________________________________

    Tableau

    Cliquer ici pour accéder au tableau final.