Le Script en PERL - Premier essai

novembre 28, 2007

Or donc, nous disposions d’un script fonctionnel mais basé sur une commande non-universelle en ce qui concerne les systèmes de type BASH.

Après un essai infructueux sur d’autres shells (csh et tcsh), qui renvoyaient des messages d’erreurs sans dire se trouvait l’erreur (ce qui aurait impliqué de revoir tout le programme), nous nous sommes lancés dans la production d’un script en PERL. Parce que substr() est une fonction native de PERL. Et ça, c’est bien !

Avertissement : N’essayez pas de retaper tout un script. C’est un coup à oublier des morceaux. Commencez par remplacer tous les “echo” par “print”, ça gagne du temps.
Ensuite, la syntaxe PERL est quand même assez proche de celle de BASH,les modifs sont de l’ordre de l’ajout de ‘;’ et… bon, en fait, il y a quelques subtilités :
Par exemple, en BASH, on avait tout un pavé pour s’assurer qu’un nom de répertoire saisi par l’utilisateur ne comportait pas de / à la fin.
En PERL, cette opération donne :

  • chomp($inputdirectory=<STDIN>);
    if ($inputdirectory=~/\w*\/$/)
    {

    chop($inputdirectory);

    }

Une petite explication ?
- la première ligne récupère une chaîne de caractère saisie par l’utilisateur ($inputdirectory=<STDIN&gt ;) et lui enlève son retour chariot final (commande chomp()). Notez le ‘;’ en fin de ligne… C’est le défaut de PERL : toute les instructions sont terminées par un point-virgule.
- la deuxième ligne est un if classique… Or is it ? En effet, PERL a l’excellente capacité de gérer les expressions régulières. Là, on a en fait pris pour condition :
“$inputdirectory est une chaîne de caractère terminée par slash”. ‘=~’ signifie qu’on va employer une expression régulière, or les expressions régulières sont ouvertes et fermées par des slashs ‘/’ . Du coup, il faut échapper un slash qui ferait partie de l’expression en le faisant précéder d’un antislash ‘\’, caractère d’échappement par défaut. De plus, ‘\w’ indique “n’importe quel caractère alphanumérique”, et l’étoile indique que \w est pris un nombre indéfini de fois (entre 0 et +∞). Autrement dit ‘\w*’ indique “toute chaîne de caractères alphanumériques”. En l’occurence, suivi de ‘\/’ et ‘$ ‘, on a “toute chaîne alphanumérique se terminant par ‘/’ : En effet, $ indique une fin de chaîne. Donc le caractère juste avant ‘$’ est le dernier de la chaîne.

Bon, ça c’est juste une petite simplification. Après, il y a notre histoire de substr facile, tout ça…
Mais abordons la grosse-modif-qui-tache tout de suite, ce sera fait.
PERL a sa façon bien à lui de gérer les fichiers. Or, on ne fait que ça dans ce script. Du coup, à l’heure actuelle, on a comme qui dirait un pépin à ce niveau là.
Mais parlons théorie :
au lieu de créer une variable $tablo qui contiendrait un nom de fichier et de devoir rajouter ‘>> ./tabs/$tablo’ à la fin de nos lignes echo, nous allons :
- ouvrir un manipulateur de fichier nommé TABLO
- avoir plein de jolies lignes du genre ‘print TABLO “<HTML>blah-blah-blah</HTML>”;
- fermer le manipulateur de fichiers.

Ouvrir un manipulateur de fichier, ça veut dire aller chercher un fichier et le donner en pâture au programme avec quelques conditions (droits de lecture/ecriture). Ca donne ça :
open (TABLO,”+>./tabs/$tablo”);

‘+>’, ça veut dire qu’on efface un contenu éventuel du fichier pour ensuite entasser ce qu’on veut dedans.
TABLO, c’est le nom du flux, qu’on retrouvera dans les commandes print.
et ‘./tabs/$tablo’, c’est le fichier vers lequel pointe notre flux.

puis on finit avec un close(TABLO);’ de bon aloi pour éviter d’écrire à nouveau dans le fichier par erreur et rendre un peu de ressource au système.

La suite dès que nous aurons un script qui fonctionne… C’est à dire très bientôt !

QP


Le Script BASH - Second Coming

novembre 27, 2007

Souvenez vous… nous vous avions laissés il y a au moins deux minutes avec un script BASH qui générait un tableau très simple.
Ca a certes fait avancer un peu notre schmilblick, mais le plus gros reste à faire. Surtout à écrire.

Pour chaque lien, il va falloir rajouter trois cases :
- le lien vers la page aspirée en local (oui, nous sommes des pirates sans scrupules, sans vergogne et sans guinaires. Yohoho, et une bouteille de rhum!)
- le lien vers la version texte brut de la page locale (parce qu’en plus on mutile les pages web ! Bwahaha !)
- le lien vers la concordance, c’est à dire le mot dans son contexte dans la page aspirée.

Pour ce faire, trois commandes Unix vont nous être utiles :
- WGET, sous la forme “wget -O <page à aspirer> <destination>
- LYNX, qui est en fait un navigateur web sous-doté en capacités graphiques, mais qui a la capacité de réduire uen page web à portion congrue. Sauf qu’il ne le fait pas dans un fichier, du coup il faudra générer un flux. Pour faire clair, la commande sera : “lynx -dump <URL page locale> >> fichier_destination”
- EGREP, qui permet
d’isoler les lignes contenant un mot bien précis dans un fichier text. On l’utilisera sous la forme : “egrep -i [char] <adresse de la page en mode texte>”.

Après une version fonctionnelle mais peu subtile en bash bourrin, nous découvrîmes quelques structures et possibilités de BASH qui allaient donner à ce script une classe folle. Mais avant tout cela, nous réorganisâmes nos fichiers contenant des URLs d’une nouvelle façon. Au lieu d’un fichier par langue (on aurait oublié de vous dire qu’on travaille dans le but de vérifier la traduction d’un terme polysémique via une table de concordances ? Bon, ben, c’est fait…), nous aurons un fichier par sens, dont le contenu sera rangé de la sorte :
<SENS>
FR
<liste d’urls en français>
EN
<liste d’urls en anglais>

Voyons maintenant ce que cela nous apporte.

Tout d’abord, BASH permet d’exploiter des procédures (aka “fonctions”), ce qui permet de soulager le programmeur qui voudrait relire son script, ou pire : le modifier (a-t-on idée, aussi !). Une fonction BASH s’écrira sous la forme :

  • fonction()
    {

    <jeu d’instructions>

    }

Et elle sera appelée directement par son nom : fonction, sans plus de fioritures.

Ensuite, la structure case permet de remplacer avantageusement une structure du genre if then elsif elsif else, bref, un choix multiple plein d’indentations qui finissent par mettre le code hors de l’écran. Un exemple (et là on avait pas encore tout le code) :

2-2b.png

Case, par contre, ça donne un truc du genre :

  • case variable in
    cas1 )
    <série d’instructions> ;;
    cas2 )
    <série d’instructions> ;;

    casN)
    <série d’instructions> ;;
    esac

( avec cas1, cas2, casN des chaînes de caractères, ou des valeurs suivant l’utilisation. Ici, des chaînes de caractères).

Du coup, on a désormais un script BASH écrit avec des appels de fonctions qui n’utilisent que des variables globales (ça facilite la vie) et une structure principale qui est une boucle imbriquée avec gestion de cas. Et ça donne, en gros, ça :
projet-bash-final.jpg

Les contextes sont encore à implémenter.
Mais il y a pire ! Il s’est soudain avéré que l’attribut substr de la commande expr n’était pas implémenté sur certaines versions de BASH. Zut et flûte ! (oui, on se censure un peu, là…)

Du coup, il nous a fallu trouver une autre solution.
parce que reprogrammer substr comme si de rien n’était, c’est franchement too much.
Et donc, nous nous sommes documentés. Et nous avons découvert…

Suspense.

Suspense..

Suspense…

nous avons découvert que la fonction substr était nativement implémentée dans le langage … PERL.
et comme nous sommes capables de raisonner et tirer des conclusions, nous décidâmes de réécrire le programme en PERL. Logique.
Mais ceci est une autre histoire…


Le script BASH - First Blood

novembre 27, 2007

 

Un script, un script… C’est bien joli. Mais pour faire quoi ?
On aurait pu faire un script du genre :
#!/bin/bash
echo “Hello World!”
Mais on aurait pas été plus avancés. Ici, il s’agit de réaliser un script prenant en entrée une liste d’URLs contenues dans un fichier texte et dont les pages web contiennent un mot-clé (ici, le mot “char”). Ce script rend en sortie une page au format HTML, contenant un tableau, qui lui-même contient des liens vers :
- chaque page listée
- une copie locale de chaque page
- une version texte brut de chaque page
ET surtout, une ligne de concordance avec le mot “char” dans son contexte.

Première étape : traiter les données en lecture

Dans un premier temps, nous avons étudié les différentes commandes à prendre en compte dans la programmation de ce script. L’idée que nous en avions au départ était de lire le fichier d’urls et de placer les urls dans un tableau en réalisant le lien vers la page web concernée. Le principal problème avec ce script était que le fichier d’input contenait les urls classées par “sens”. Donc quand le script lisait le fichier, il fallait qu’il soit capable de différencier une ligne “url” d’une ligne de “sens” (ou d’une ligne vide).
or, une ligne d’url commence nécessairement par “http”. Donc, il suffisait à notre script de prendre les quatres premiers caractères de chaque ligne, et en fonction de ces caractères :
- de créer une ligne avec un lien si les 4 caractères étaient “http”
- de créer une ligne de texte brut dans le cas contraire.

A vue de nez, facile :

  • compteur=1
    for ligne in `cat <nom de fichier>` {
    deb= ‘expr substr $ligne 1 4’

On implémente un compteur, puis on lance une boucle qui prend les lignes du fichier une par une (via la commande cat) avant de leur faire subir une série d’opérations. On commence par expr avec l’attribut substr 1. Cette commande permet de copier les 4 premiers caractères de la variable $ligne (qui, par une habile coïncidence contient le texte de la ligne à traitée) et de les placer dans la variable $deb. On n’a plus ensuite qu’à regarder si ces 4 caractères correspondent à la chaîne de caractère “http”.

  • if [ "$deb" == "http" ] then
    <création de ligne avec lien hypertexte>
    else
    <création de ligne texte>
    fi

- Si la condition est vérifiée, alors on crée dans le tableau un lien que l’on appelle “url$compteur”, ce qui donne url1 pour le premier lien, url2 pour le second, and so on. Après quoi, on incrémente la variable $compteur de 1
- Si la condition se vautre, on prend la ligne telle quelle et on la place dans une case du tableau sans incrémenter quoi que ce soit.

Voici le résultat obtenu :

script-1.png

1 : la commande expr et surtout son attribut substr vont nous poser problème dans un futur proche… Nous en reparlerons.