Lecture et analyse d'un fichier TSV

 

Parmi les outils que Linux propose, se trouvent plusieurs langages de programmation interprêtés : Awk, Perl, Python, ... et Tcl. Tous les langages ont des points forts et des points faibles. La plus importante faiblesse de Tcl est peut-être sa réputation indue d'être lent et vieillot. Pourtant, il existe communauté de programmeurs en Tcl forte et active !

Les points forts qui caractérisent Tcl :

Comme l'a montré Steve Landers, en utilisant cette technique on peut mettre un serveur web complet avec ses pages sur une seule disquette !

Selon moi, c'est la versatilité de ce langage qui est son principal point fort. Je vais le montrer avec quelques applications très diverses.

La portion de code ci-dessous s'occupe de lire et d'analyser des fichiers "TSV" - des valeurs qui sont separées par des tabulations - comme on peut en produire avec un tableur. On lit ces fichiers ligne par ligne et on calcule la somme des valeurs. Ces sommes sont imprimées à l'ecran :

  1.   set infile [open $filename "r"]
  2.
  3.   while { [gets $infile line] >= 0 } {
  4.      set sum 0
  5.      foreach v [split $line "\t"] {
  6.         set sum [expr {$sum+$v}]
  7.      }
  8.      puts $sum
  9.   }
 10.   close $infile

Le numérotage des lignes ne fait pas partie de Tcl : il n'est là que pour faciliter l'explication du code.

Ce script ne protège pas contre des erreurs comme essayer d'ouvrir un fichier non-existent. Il est, bien entendu possible de rajouter ce genre de protections, mais ce n'est pas un cours sur Tcl, n'est-ce pas ?

La ligne 1 ouvre le fichier dont le nom est contenu la variable "filename" - le signe $ signifie qu'ici Tcl doit remplacer le nom de la variable par sa valeur. Le resultat est une "chaine" d'identification qui est mis dans la variable "infile".

Les crochets que l'on voit à la ligne 1 ont la même fonction que les apostrophes inversée (`) en Korn shell : l'interpreteur Tcl exécute le code entre les crochets et remplace le code par le résultat.

La ligne 3 est le commencement d'une boucle qui va jusqu'à la ligne 9 : les accolades définissent des blocs de code, comme dans les langages C ou Java.

A la ligne 3 on lit une ligne entière du fichier (la commande "gets"). Si ça reussit, le resultat est le nombre de caractères qui ont été lus. Sinon, à cause de la fin du fichier, le résultat est -1, donc la boucle se termine.

En Tcl le premier mot d'une ligne interprêté comme la commande qui doit être executée. La commande "set" est utilisée pour mettre une nouvelle valeur dans une variable. Le fait que la valeur soit numerique, une chaine ou un liste de chaines n'est pas important : on utilise pareillement la commande "set".

La "liste de chaines" (ou plus simplement liste) est une des plus importantes structure de données en Tcl : comme les "arrays" en C, mais plus faciles d'utilisation. Toute la gestion de la mémoire est prise en compte par Tcl lui-même : la taille de liste sera adaptée selon les besoins.

La ligne 5 contient deux des commandes qui manipulent des listes : - _foreach_ qui est une commande d'itération par élements d'un liste. - _split_ qui est la commande pour convertir une chaine arbitraire en liste propre. Dans ce cas, le caractère de tabulation (représenté par "\t", comme en C) est donné comme séparateur de la chaine.

La boucle lancée par la commande foreach parcourt tous les éléments de la liste construite de cette manière. La valeur de l'élément est ajoutée a la somme et quand la boucle est finie, la somme a été determinée.

Il ne reste qu'à imprimer le résultat (ligne 8).

On peut le constater : lire des fichiers TSV est une procédure très simple, on n'a besoin que de quelques commandes très simples.

Bien sûr, si les fichiers pouvaient contenir d'autres choses que des nombres valides, il faudrait prendre quelques précautions. Par exemple, celle-ci :

     if { [string is double $v] } {
        set sum [expr {$sum+$v}]
     } else {
        puts "Pas un nombre !"
     }

En remplaçant la ligne 6 par ce bout de code, le programme devient bien plus robuste : la commande _string is double_ examine son argument, si c'est un nombre valide, elle retourne "vrai", sinon "faux".