Beruflich Dokumente
Kultur Dokumente
Auteur :
Arnaud LAPREVOTE
Linbox/Free&ALter Soft
152, rue de Grigy
57070 METZ
tel: 03 87 50 87 90 − 06 11 36 15 30
Email : arnaud.laprevote@linbox.com
1. Introduction
Il était une fois un programmeur qui avait passé des milliers d'heures à programmer en C,
particulièrement des applications de calculs scientifiques (traitement vidéo). Avec les années, il
avait acquis une grande facilité dans l'écriture des programmes C, et en même temps une certaine
impatience.
Autant le C le satisfaisait pour le calcul scientifique, autant dès qu'il fallait traîter des fichiers ou des
chaînes de caractères, il trouvait que c'était fastidieux et surtout générateur d'erreurs de manière
inacceptable.
Comme tout le monde, il avait entendu parler des langages de scritps genre perl, tcl/tk, et autres
(python). A l'occasion de l'installation de son PC sous linux, il prit le temps de commencer à
programmer en tcl.
Ce programmeur, c'est moi. Et j'ai très envie de vous faire partager cette passion pour mon langage
préféré.
1.2. Et la concurrence ?
Tcl / Tk 1
Il y a de très nombreux concurrents au Tcl/Tk :
• Perl,
• Python,
• Scheme (lisp),
• dans une certaine mesure PHP,
• Visual Basic,
• Java.
Tous ces langages ont des avantages et des inconvénients. Mes critères de choix principaux sont :
Un dernier avantage est que le Tcl n'a pas une ambition infinie. Le Tcl ne veut pas TOUT faire.
C'est juste un langage de "colle" pour faire tenir un ensemble d'application ensemble. Si vous
voulez faire des choses très grosses ou très complexes ou très rapides, vous êtes priés de vous
tourner vers le C, le C++ ou le java.
A cette lumière, il ne reste que le python et le tcl, à la limite le perl. La syntaxe du perl me rend fou,
donc je l'exclus. Je m'intéresse au Python.
• fonctions réseaux (socket) intégrées très élégamment au langage. Un serveur web se fait en
claquant des doigts,
• faciliter d'intégration du tcl dans une application existante,
• très grande robustesse du langage,
• faciliter d'intégration de fonctions C dans le Tcl,
• la compatibilité ascendante n'est pas une théorie mais une réalité,
• très forte cohérence due à une origine universitaire.
1.4. Inconvénients
• le langage n'est pas en GPL => moins grande dynamique du langage que le python ou le
perl,
• il n'est pas possible de définir de vrais structures en tcl (au sens C du terme). Cela peut
nuire à la lisibilité des programmes et limite la taille de ce que l'on peut programmer. On
peut se tourner vers les extensions objets du tcl pour avoir ces fonctions,
• il manque une IDE libre avec un déboggueur intégré pour faciliter la prise en main par les
débutants.
2. Historique
Tcl / Tk 2
Tcl fut créé en 1990 par John OUSTERHOUT à l'Université de Berkeley. C'est un language de
"collage" pour attacher ensemble plusieurs applications. C'est un langage interprété mais compilé à
la volée depuis la version 8.0. La version actuelle est Tcl 8.3.
Après Berkeley, John Ousterhout est passé chez Sun, puis il a créé sa propre société Scriptix qui
est devenue ensuite Ajuba Solutions et a été rachetée récemment. Des centaines de programmes
et de société utilise le tcl, mais souvent de manière souteraine. Tcl est donc un langage discret.
3. Ressources utiles
"Practical Programming in Tcl/Tk" ISBN: 0−13−038560−3 par Brent Welch <welch@acm.org>, Ken
Jones, et Jeff Hobbs en partie en ligne sur http://www.beedub.com/book/ : la bible incontournable
"Graphical Appications with Tcl&Tk" ISBN : 1−55851−471−6 par Eric F.Johnson : un très bon livre
pour commencer.
"TCL/TK Apprentissage et référence" ISBN : 2−7117−8679−X par Bernard Desgraupes . Je l'ai
juste feuilleté, je suis très vexé de ne pas l'avoir écrit.
tclsh
Ou sous windows, allez dans le menu démarrer, déroulez le sous−menu tcl puis cliquez sur tclsh ou
wish(plutôt wish).
Vous obtenez alors un prompt en %. Taper ce qui suit % dans les lignes suivantes :
Tcl / Tk 3
Les points clés de cet exemple sont :
COMMANDES
set nom_de_variable "valeur"
puts "chaine de caractères"
incr nom_de_variable_numérique [incrément]
COMMANDES
for { initialisation } { end condition } { incrementation } {
code running at each loop
}
SYNTAXE
command [argument1] [argunment2]
first_command; second_command
"$substitution" "\$caracter printed as is"
[immediate execution] {execute as late as possible}
#remarque
5. La syntaxe du tcl
Un des problèmes du tcl est sa simplicité. Concernant sa syntaxe, il n'y a guère que 2 choses à
savoir.
ET PAS
toto = "xxxx"
Les arguments de la commande sont séparés les uns des autres par des espaces.
D'où obligatoirement :
Tcl / Tk 4
for {set i 0} {$i <4} {incr i} {
}
Et non pas
Il y a une finesse en tcl. Les substitutions. L'interprétation d'une ligne se fait en 2 temps :
• substitution de tout ce qui est substituable (variable, code entre crochets []),
• exécution de la commande.
Donc :
L'exécution d'un code entre [] et la substitution dans l'expression appelante du contenu de [] par son
résultat. C'est ce que l'on appel de la programmation fonctionnelle. Le lisp est l'archétype de ces
langages. Le tcl permet de mélanger élégamment programmation fonctionnelle et procédurale.
Dans certains cas (les traitements sur des chaînes de caractères) la programmation fonctionnelle
est TRES (très, vraiment très, j'insiste encore ? non) pratique.
Pour affiner ces notions, on peut ajouter que le caratère (antislash), force l'interprétation du
caractère le suivant comme étant un simple caractère et rien d'autre :
Tcl / Tk 5
TOTO
% set tata "\$toto"
$toto
% set tata Ce\ qui\ suit\ est\ une\ seule\ chaîne
Ce qui suit est une seule chaîne
% puts "\[ pas d'interprétation hative ]"
[ pas d'interprétation hative ]
Et que l'on peut utiliser les accolades autour d'un nom de variable pour lever l'ambiguité :
Si vous avez complètement compris ce qui précédait, alors une friandise (sinon c'est le moment de
piquer un roupillon, de papoter avec les voisins, de se taper un carton, de relever ses SMS, et de
noter qu'il faut relire le paragraphe qui suit dans 15 jours).
L'instruction eval permet de forcer une évaluation supplémentaire, et de temps en temps c'est
fantastique (le préprocesseur de tcl est tcl contrairement au C):
#!/usr/bin/tclsh
set var1 "Un"
set var2 "Deux"
set var3 "Trois"
set var4 "Quatre"
set var5 "Cinq"
set var6 "Six"
for { set i 1 } { $i <7 } { incr i } {
set command "puts \$var$i"
eval $command
}
Un
Deux
Trois
Quatre
Cinq
Six
6. Types de données
• scalaire : tcl 7.6 − chaînes seulement => tcl 8.0 − chaînes et valeurs.
Tout est chaîne en tcl : c'est la clé de la facilité d'interaction : toute fonction peut envoyer des
résultats à n'importe quelle autre.
Tcl / Tk 6
%string range $str1 0 4
01234
% string compare $str1 "101112131415"
−1
%proc frame_string { str } {
format "###−>%sArnaud LAPREVOTEArnaud LAPREVOTE Arnaud LAPREVOTE
COMMANDES
string length $a_string
string index $a_string index ; #(0 is first)
string range $a_string first_index last_index
SYNTAXE
proc function_name { list of args } {
instructions
return 5
}
COMMANDES Description
list first_elt second_elt ... Création d'une liste. Renvoi une liste.
llength $a_list Renvoi le nombre d'élément de la liste
lindex $a_list elt_nber Renvoi l'élement n° elt_nber de la liste. elt_nber peut être end
(dernier élément).
lrange $a_list start_nber Renvoi une liste composée des éléments commençant ) start_nber
end_nber et finissant à end_nber
lsort $a_liste Ordonnancement de la liste. De nombreuses options permettent de
classer en ordre croissant / décroissant, en utilisant un élément
d'une sous−liste comme clé, en ordre numérique, ... Renvoi une liste
linsert $a_list nber Insère un élement dans une liste à l'endroit indiqué. Renvoi une liste.
elt_to_insert
lappend a_list Ajoute les éléments suivant à la fin de la liste. ATTENTION
elt_to_append_at_the_end LAPPEND NE RENVOI PAS DE LISTE. IL MET AU BOUT DE LA
LISTE NOMMEE a_list LES ELEMENTS.
split "chaine de caractère" Transforme une chaîne de caractères en une liste. Le séparateur est
[caractère] le caractère fourni en second paramètre.
Tcl / Tk 7
7.2. Chaînes et expressions régulières
Les expressions régulières sont une fonction clé des langages de scripts (ksh, perl, awk, tcl, python,
...). Elles ne sont pas du tout naturelles, mais une fois comprise, elles sont un outil très puissant.
Vous devez les essayer !
Une seule méthode pour survivre en United States of Regular Expressions : essayez d'abord, puis
programmez. Même une ceinture noire 4ème dan de tcl fait comme cela.
COMMANDES
regexp {sf(first expr)(second expr)} $string \
matching_string first_matching_str second_matching_string
Tcl / Tk 8
%puts_array good
first_name = Laprevote
name = FreeSoft
sur_name = Arnaud
COMMANDES EXPLICATION
set toto(tata) "string" Initialisation à string de l'entrée tata dans le tableau toto
array exists name Renvoi 1 si le tableau name existe
array names name Renvoi la liste des entrées du tableau
array get name Liste de paiares clé valeur du tableau name
array set name list Initialise le tableau name en utilisant une liste à la syntaxe identique au
résultat de array get name
parray name Affichage du tableau name
upvar $name Passage d'un tableau par pointeur à une fonction
name_to_use
this_proc toto
8. Commandes de contrôle
if { condition } {
#code à exécuter si la condition est vraie
} elseif { condition2 } {
# code à exécuter si la condition2 est vraie
} else {
# code à exécuter si aucune condition n'est vraie
}
while { condition } {
# code à exécuter tant que la condition est vraie
}
switch valeur {
value1 {
#code à exécuter si valeur remplie la condition value1
}
value2 {
#code à exécuter si valeur remplie la condition value2
}
default {
#code à exécuter si aucune des conditions précédentes n'est vraie
}
}
Les options −exact −glob et −regexp permettent de choisir le type de règle de comparaison utilisé.
Pour distinguer les options de switch de l'argument final de switch on utilise −− :
Tcl / Tk 9
}
Si l'on est en mode −exact de switch, on cherche la section de switch dont la valeur est strictement
identique à l'argument de switch.
Si l'on est en mode −glob, alors * remplace n'importe quel caractère zéro ou plusieurs fois. Donc :
set i 0
while { $i <200 } {
switch −exact −− $i {
0 {
puts "Je ne vois pas de mouton"
}
1 {
puts "Whoua un mouton là"
}
100 {
puts "T'en a pas marre des moutons ?"
puts "Tape Ctrl−c pour arréter du plouc !"
}
default {
puts "$i moutons"
}
}
incr i
}
puts "J'ai une indigestion de mouton,"
puts "plus le mal de mer et la tête lourde"
puts "avec une grosse envie de dormir. J'arrête."
Exemple
Tcl / Tk 10
} elseif { $i == 57 } {
puts "Un mosellan"
set pluriel "s"
}else {
set pluriel "s"
}
puts "$i mouton${pluriel}"
}
Enfin, il ne faut pas oublier l'instruction foreach. Cette instruction permet de boucler sur les
éléments d'une liste.
La commande permettant de définir une procédure est proc. C'est une commande comme une
autre qui prend 3 arguments :
Exemple :
#!/usr/bin/tclsh
set DEBUG 1
proc debug { message } {
global DEBUG
if $DEBUG {
puts $message
}
}
Tcl / Tk 11
9. Entrées/sorties et gestion des erreurs
9.1. Entrées/sorties
La commande open retourne un identifiant qui sera utilisé lors des appels aux autres commandes.
Ex:
set f [open "toto.txt" "r"]
=> file4
set toto [read $f]
=> xxxxxx
close $f
Ou encore :
set f [open "titi.txt" w]
=> file4
puts $f "Ecrit ce texte dans le fichier"
# puts permet d'écrire dans un canal déterminé (défaut sortie standard)
close $f
La commande error permet elle de générer une erreur dans un code et d'y associer un message
d'erreur.
Tcl / Tk 12
MOINS USITEES
clock exit package split unknown after
info pid rename string unset
fblocked interp pkg_mkIndex subst update
continue fconfigure join scan uplevel
bgerror eof seek tclvars upvar
error fileevent library pwd tell vwait
filename history read socket time
cd flush trace
Comme vous pouvez le remarquer, cela représente vraiment peu de commandes, ce qui explique la
facilité d'apprentissage du tcl.
L'objectif est d'écrire un programme tcl qui parcourrera un fichier html et donnera la liste des noms
entre les tags html h1 et /h1 et les variantes de ces tags h2 /h2 et h3 /h3. La liste sera imprimée sur
la sortie standard. Il faut tester sur la page suivante :
http://www.w3.org/TR/REC−html32.html
Sauvegardez cette page dans /tmp sous le nom test.html, puis lancez votre programme dessus.
Vous souhaitez écrire un programme qui a des options d'appel en ligne de commande. En
particulier :
−h[elp] : affichage d'une aide
−f[ile] nom_de_fichier : fichier d'entrée,
−l[evel] [0−9]+ : niveau de recherche de 1 à ce que vous voulez.
Les arguments peuvent être passés sur la ligne de commande dans n'importe quel ordre. A la fin de
l'initialisation de la fonction vous avez 3 drapeaux à 1 ou 0 indiquant si les options −help, −file ou
−level ont été appelées. Le nom du fichier d'entrée et le niveau sont stockés dans les variables
filename et level.
#!/usr/bin/tclsh
puts "argc : $argc"
puts "argv : $argv"
set i 0
foreach arg $argv {
puts "argument $i : $arg"
incr i
}
puts "argv0 : $argv0"
args.tcl
Tcl / Tk 13
$ ./args.tcl
argc : 0
argv :
argv0 : ./args.tcl
Vous allez créer une machine à état. Le passage d'un état à un autre se fait lorsque l'on passe à
l'argument suivant. L'état de base de cette machine est :
De cet état, vous allez sauter à l'état suivant lors du test de l'argument suivant, en fonction
de la valeur de arg. Si arg est à −f*, alors vous sautez dans l'état is_file, et vous initialisez filename
avec $arg. Au passage, vous initialisez le drapeau correspondant à la présence du nom de fichier
sur la ligne de commande à 1. Il faut ensuite revenir à l'état check_arg.
Il vous reste juste à prévoir les états correspondants pour help et pour level et à les gérer de même.
Bon courage. Merci de ne pas oublier le guide à la fin de la visite. A votre bon coeur M'sieur dame.
Tcl / Tk 14