ioProgrammo N°19, Novembre 1998 ©Copyright DIEMME Editori
#!/usr/bin/tclsh # si inizia con un bel commento puts "Ciao, mondo"; puts stdout {Ciao, mondo} # stampa due volte Ciao, mondo # per default il comando puts \ stampa anche un ritorno a capo # stdout è un argomento predefinito di puts \ e forza la scrittura sullo standard output puts "Sono le ore [clock format [clock seconds]]" # stampa l'ora corrente # clock format e clock second sono comandi predefiniti # il risultato di clock second viene passato a clock format puts {Sono le ore {clock format [clock seconds]}} # stampa Sono le ore clock format [clock seconds] set variabile 5 # assegna a variabile il valore 5 puts -nonewline "variabile vale $variabile" # stampa variabile vale 5 senza tornare a capo # -nonewline è un argomento predefinito di puts \ usato per impedire il ritorno a capo puts Linux # stampa Linux # errore, il commento non è preceduto \ dal punto e virgola puts "Slackware \ vs \ RedHat"; # stampa Slackware vs RedHatE' giunto il momento di usare queste regole con gli altri elementi del linguaggio. Iniziamo subito da i più importanti.
set nome pippo # assegno a nome il valore pippo set a 5; set b 2 set c [expr 5/2] # assegno a c il risultato della divisione 5/2 puts $c # stampa 2 set d $c # assego alla variabile d \ il contenuto della variabile c puts [expr 5.0/2] # stampa 2.5 set pi_greco [expr 2*asin(1.0)] # assegno a pi_greco 3.1415926535897931 unset pi_greco; # elimino pi_greco if {![info exist pi_greco]} { puts "pi_greco e' stato cancellato" } # la condizione e' vera per cui stamperà \ pi_greco e' stato cancellato set .o oggetto! puts $.oy; # errore, servono le graffe puts ${.o}y; # stampa oggetto!yVi sarete accorti che nell'esempio l'operazione 5/2 non stampa 2.5, ma 2. Questo perchè tcl, per default, considera i numeri degli interi. Se vogliamo stampare la parte decimale del risultato si deve scrivere almeno un numero che partecipa all'operazione con la virgola (la virgola viene scritta con un punto). Un altro approccio consiste nell' indicare all'interprete il tipo di precisione che si dovrà usare nei calcoli, e questo viene fatto con un apposito comando:
set tcl_precision 5 # 5 cifre dopo la virgola puts [expr 1/3] # stampa 0.33333Il numero ed il valore degli argomenti passati allo script sulla riga di comando sono rispettivamente memorizzati in due variabili speciali: argc e argv
puts "Programma: $argv0" # $argv0 contiene per default il nome dello script puts "Numero di argomenti: $argc" # stampa il numero di argomenti passati allo script set i 0 foreach arg $argv { puts "Argomento $i: $arg" incr i } # stampa il numero di ogni argomento ed il suo contenutoPassiamo agli array. Gli array in tcl sono implementai come tabelle hash nel senso che l'indice di un elemento dell'array non è un intero ma una stringa. Il comando più usato per manipolare gli array è array dotato di un discreto numero di opzioni come size, get, names.Vediamo qualche esempio.
set password(root) segreta # root e' l'indice # segreta e' il primo elemento dell'array set password(pino) goldrake set password(mario) mazinga # ho definito un array di nome password \ di tre elementi puts "La password di root e': $password(root)" # stampa La password di root e': segreta puts [array size password] # stampa 3 # array size e' un comando predefinitoLavorando con Linux spesso capita di far riferimento alle variabili d'ambiente. Quest'ultime in tcl sono memorizzate in un array speciale di nome env.
puts "$env(TERM)" # stampa a video il valore della variabile d'ambiente TERM set environment [array get env] foreach {var valore} $environment { puts "$var=$valore" } # stampa tutte le variabili d'ambinete # come il comando set di LinuxEd eccoci arrivati alle liste. Innanzitutto una lista è un elenco di variabili scalari (prese singolarmente o a gruppi) o di array.Il "tipo" lista di array è quindi un tipo di variabile valido. Ogni variabile o gruppo di variabili è chiamato elemento della lista. Per esempio la scrittura
set mialista {a b c d e f} set mialista2 {{a b} {c d} {e f}}definisce una lista di nome mialista composta da 6 elementi (le prime sei lettere dell'alfabeto) ed un'altra di nome mialista2 dotata di tre elementi (le coppie a b, c d, e f). I comandi per il trattamento delle liste sono molto usati in tcl. I più utili sono
llength lista Restituisce il numero di elementi di una lista
lindex lista indice Restituisce il valore di un elemento della lista (se l'indice è uguale a zero, si punta al primo elemento della lista)
linsert lista indice elemento ?elemento elemento ...? Inserisce uno o più elementi in una lista
lsort ?opzioni? lista Ordina una lista. Le opzioni più comuni sono:
-ascii (ordina con logica lessicografica)
-integer (converte egli elementi in numeri interi ed ordina in base al valore numerico)
-increasing (ordina in senso crescente)
-decreasing (ordina in senso decrescente)
LAVORIAMO CON LE STRINGHE
In tcl qualsiasi cosa che proponiamo all'interprete viene considerata una stringa. Anche i numeri sono stringhe fino a che non vengono usati con il comando expr. Solo in questo caso vengono valutati per quello che sono realmente, cioè numeri, e quindi usati per eseguire operazioni matematiche.
Premesso ciò, visto che tcl è come il Perl un linguaggio rivolto alla gestione di dati in formato testuale, il programmatore dispone di una nutrita gamma di comandi per la manipolazione delle stringhe. string, split e join sono quelli più usati.
Il primo è usato per confrontare due stringhe oppure per compiere speciali operazioni su di esse.
String ha la seguente sintassi
string opzione argomento ?argomento ...?Le opzioni più comuni sono compare, length, match e trim. Ce ne sono molte altre ma per una disamina più dettagliata consiglio di far riferimento al manuale (lo spazio è tiranno, ahimè). La prima, compare ("string compare stringa1 stringa2"), esegue una comparazione carattere per carattere di due strighe. Il confronto avviene secondo logica lessicografica ovvero secondo l'ordine dei caratteri nel dizionario. Il risultato può essere -1, 0 o 1 rispettivamente se stringa1 è minore, uguale o maggiore di stringa2. Il comando "string length stringa" ritorna il numero di caratteri di una stringa. L'opzione trim ("string trim stringa ?caratteri?") restituisce la stessa stringa senza i caratteri specificati che si trovano all'inizio o alla fine della stringa stessa. In sostanza "tagliamo" dalla stringa i caratteri iniziali e finali che non ci interessano. Se l'argomento caratteri non viene specificato, dalla stringa verranno eliminati i blank (spazi, tab, ritorni a capo). Infine il comando string associato all'opzione match ("string match modello stringa") permette il confronto di una stringa con un modello. Se il riscontro ha successo il comando restituisce 1 (per esempio nel caso in cui modello e stringa siano uguali), 0 in caso contrario. E' interessante osservare come il modello di confronto possa contenere alcuni caratteri speciali che possiamo considerare come operatori di matching. L'asterisco * riscontra qualsiasi sequenza di caratteri nella stringa. Il punto di domanda ? matcha (orribile questo termine, ma dà l'idea del successo dell'operazione di riscontro) un singolo carattere. Con le parentesi quadre ([abcd] oppure [a-d]) possiamo forzare il riscontro di un set di caratteri, mentre con il backslash \ riscontriamo un singolo carattere. Il backslash inoltre è indispensabile per matchare (questo è ancora più orribile, sigh!) proprio i carattrei * ? [ ] e \ togliendo loro il significato speciale che possiedono.
string compare "abcdefgh" "ilm" # ritorna -1 # infatti "ilm" è più grande di "abcdefgh" # e questo perché ha dei caratteri che nel # dizionario occupano una posizione superiore string compare "abcd" "abcd" # ritorna 0 # infatti le due strighe sono # lessicograficamente uguali string compare "z" "a" # ritorna 1 puts [string trim ".abc." .] # stampa abc set nome agilulfo if {[string length $nome] > 5} { puts "Nome lungo" } else { puts "Nome corto" } # stampa Nome lungo set numero "041-123456" if {[string match 041* $numero]} { puts "Prefisso di Venezia" } else { puts "Prefisso fuori Venezia" } # stampa Prefisso di VeneziaProseguiamo. Il comando split viene usato in questo modo:
split stringa ?caratteri separatori?e ritorna una lista i cui elementi sono le porzioni della stringa divise dai caratteri separatori. Se l'argomento caratteri è una stringa vuota, allora ogni carattere della stringa viene considerato carattere separatore, mentre se viene omesso, per default il carattere separatore sarà lo spazio. Tra l'altro se la stringa contiene dei caratteri separatori adiacenti verrà generato in corrispondenza di quei caratteri un elemento vuoto della lista.
puts [split root:0:0 :] # stampa root 0 0 puts [split www.linux.org .] # stampa www linux org puts [split "Ciao, mondo" {}] # stampa c i a o , {} m o n d o puts [split "tizio caio sempronio"] # stampa tizio caio sempronio split "rosso||verde||blu" | # ritorna "rosso {} verde {} blu"Per finire vediamo come funziona il comando join. Si tratta dell'esatto contrario del comando split, per cui invece di creare una lista spezzando una stringa, crea una stringa a partire da una lista.
join lista ?caratteri di unione?Se l'argomento "caratteri di unione" viene omesso, la stringa risultante sarà composta da ogni singolo elemento della lista separato da uno spazio.
puts [join [split "www.sun.com" .] \0] # stampa wwwsuncom set lista {www diemme it} set url [join $lista .] puts http://$url # stampa http://www.diemme.it
tar -zxf tcl7_6p2.tar.gz tar -zxf tk4_2p2.tar.gzI pacchetti verranno decompressi rispettivamente in ~/tcl7.6 e ~/tk4.2 creando per entrambi una nuova struttura di directory in cui sono contenuti i sorgenti in C. Entriamo in ~/tcl7.6/unix ed eseguiamo i comandi
configure make make installFacciamo la stessa cosa nella directory ~/tk4.2/unix Al termine delle compilazioni troveremo nella directory /usr/local/lib i file di libreria di tcl/tk mentre i binari saranno posizionati in /usr/local/bin Non ci resta che creare due link simbolici in /usr/bin con i comandi
ln -sf /usr/local/bin/tclsh7.6 /usr/bin/tclsh ln -sf /usr/local/bin/wish4.2 /usr/bin/wishe settare le variabili d'ambiente TCL_LIBRARY e TK_LIBRARY scrivendo nel file /etc/profile o ~/.profile le righe
export TCL_LIBRARY=/usr/local/lib export TK_LIBRARY=/usr/local/lib
Data creazione HTML: Marzo 1999
Autore: Francesco Munaretto
E-mail: NoSpam@thank.you