Programarea sub Linux n Tcl Introducere n limbajul
Programarea sub Linux în Tcl Introducere în limbajul Tcl Substituţii Comentarii Acolade şi ghilimele Variabile Expresii Comenzi de control al fluxului. Proceduri în Tcl Lucrul cu şiruri de caractere în Tcl
Introducere în limbajul Tcl • Scripturile Tcl se elaborează în aceeaşi manieră ca şi scripturile în shell. Numele interpretorului Tcl este tclsh şi acesta se găseşte de regulă în directorul /usr/bin. La intrarea în sistem, variabila de mediu PATH include directorul /usr/bin. În consecinţă, puteţi lansa shellul Tcl tastând direct tclsh. Pe linia imediat următoare, va apărea semnul procent (%); acest semn este promptul interpretorului Tcl. Pentru a determina versiunea Tcl de care dispuneţi, tastaţi info tclversion la promptul interpretorului Tcl. Acesta va răspunde afişând versiune limbajului Tcl: tclsh %info tclversion 8. 0 % • Puteţi acum să încercaţi să executaţi în mod interactiv programul Tcl următor, care afişează şirul de caractere Hello, World! la ieşirea standard (adică pe ecran): %puts "Hello, World!" Hello, World! % • Tastaţi exit pentru a părăsi shellul Tcl (tclsh).
• Shellul Tcl prelucrează imediat o comandă introdusă şi afişează rezultatele acesteia, după care afişează promptul, aşteptând o nouă comandă. Deocamdată, puteţi tasta exit pentru a părăsi interpretorul Tcl. Pentru a pregăti şi lansa un script Tcl, se procedează similar cu shell-scripturile. Interpretorul Tcl procedeaza similar cu bash pentru procesare. • Atunci când scrieţi comenzi Tcl, trebuie să separaţi numele comenzii de argumentele acesteia prin spaţiu sau tab. Sfârşitul unei comenzi este marcat printr-un caracter linie nouă sau prin punct şi virgulă (; ). Puteţi insera două comenzi pe aceeaşi linie, dacă le separaţi prin punct şi virgulă. Prin urmare, puteţi scrie următoarea linie de comandă: puts Hello, ; puts World; Hello, World! • Rezultatul apare despărţit pe două linii, deoarece comanda puts adaugă în mod prestabilit un caracter de trecere la linie nouă. • Utilizaţi un backslash () la sfârşitul unei linii pentru a putea continua un şir de comandă pe linia următoare. În consecinţă puteţi rescrie şirul de comandă pentru afişarea mesajului Hello, World! în modul următor: Puts "Hello, World!"
Substituţii • Substituţia variabilelor. Tcl utilizează variabilele ca şi Bash. Dacă în faţa numelui unei variabile apare semnul dolar ($), interpretorul va înlocui numele variabilei cu valoarea acesteia. Pentru a defini o variabilă într-un script Tcl se utilizează comanda set. • Exemplu. Se defineşte o variabilă numită cont care valoarea 100, după care se afişează conţinutul variabilei. %set cont 100 %puts $count 100 Substituţia secvenţelor „backslash”. Puteţi îngloba caractere speciale, cum sunt linie nouă şi caracterul de tabulare, într-un anumit cuvânt, utilizând acest tip de substituţie. Este suficient să tastaţi caracterul backslash, urmat de unul sau mai multe caractere; interpretorul va înlocuii această secvenţă cu un caracter neafişabil. Aceste secvenţe corespund cu secvenţele escape din standardul ANSI C.
• Secvenţele backslash pe care interpretorul limbajului Tcl le înţelege: Secv. Caracter ce înlocuire b Backspace (0 x 8) f Salt la pagină (0 xc) n Linie nouă (0 xa) r Retur de car (0 xd) t Tab orizontal (0 x 9) v Tab vertical (0 xb) <newline> Caracterul linie nouă şi spaţiul de pe linia următoare sunt înlocuite cu un singur spaţiu \ Un singur backslash () * Ghilimele duble (*) 00 Valoarea specificată (de cel mult trei cifre) este interpretată în octal xhh Valoarea specificată este interpretată în hexazecimal
• Substituţia comenzilor. O anumită parte a şirului de comandă este evaluată şi apoi înlocuită prin rezultatul întors, înainte ca interpretorul să prelucreze întregul şir de comandă. • Exemplu: Comanda string lenght „Hello, World!” returnează valoarea 13, care reprezintă lungimea şirului de caractere. Pentru a atribui unei variabile numite len lungimea acestui şir, tastaţi următoarea comandă: set len [string lenght „Hello, World!”] Interpretorul va evalua comanda cuprinsă în interiorul parantezelor pătrate, înlocuind apoi partea corespunzătoare a şirului de comandă cu valoarea comenzii evaluate. Prin urmare, şirul de comandă va deveni: set len 13 comanda set atribuind variabilei len valoarea 13.
Comentarii • Începutul unui comentariu este marcat prin semnul „diez” (#); interpretorul limbajului Tcl va ignora restul liniei, începând cu acest semn. În Tcl, există totuşi o restricţie asupra comentariilor; acestea nu pot începe în interiorul unei comenzi. Înainte de a începe un comentariu, trebuie ca şirul curent de comandă să se termine. • Exemplu: % puts „Hello, World!” #Acesta este un comentariu wrong #args: should be „puts” ? -nonewline? ? field? string Comanda puts va parcurge restul liniei, semnalând o eroare în ceea ce priveşte numărul de argumente. Soluţia este de a pune caracterul punct şi virgulă înainte de diez, ca în exemplul: % puts „Hello, World!”; #Acesta este un comentariu Hello, World! • Atunci când doriţi să inseraţi un comentariu la sfârşitul unei comenzi Tcl, nu uitaţi că înainte de semnul diez să puneţi caracterul punct şi virgulă. Acest caracter indică sfârşitul şirului de comandă şi vă permite să începeţi un comentariu.
• • • Acolade şi ghilimele Pentru gruparea mai multor cuvinte, se utiliz. acoladele ({ }) sau ghilimelele (”. . . ”). Utilizaţi ghilimele pentru transferul argumentelor care conţin spaţii sau caractere punct şi virgulă, utilizate în mod obişnuit cu rol de caractere de terminare a comenzii. Ghilimelele nu fac parte din comandă, fiind folosite numai la marcarea începutului, respectiv sfârşitului, unui grup de cuvinte. Exemplu în care se utilizează ghilimelele pentru gruparea cuvintelor: %puts ”Hello, World!” Hello, World! %puts ”Introduceţi 1; în caz contrar, fişierul nu va fi salvat!” introduceţi 1; în caz contrar, fişierul nu va fi salvat! La gruparea unor cuvinte cu ajutorul ghilimelelor, se pot efectua toate tipurile de substituţii. Exemplu: %puts ”În şirul ´hello´ sunt [string lenght hello] caractere”; În şirul ´hello´, sunt 5 caractere Interpretorul tcl va înlocui subşirul cuprins între paranteze cu rezultatul comenzii string lenght hello, care returnează numărul de caractere din şirul hello, adică 5.
• O altă posibilitate de a grupa cuvintele este prin intermediul acoladelor. Atunci când includeţi cuvintele între acolade, interpretorul limbajului Tcl nu efectuează nici una dintre substituţiile cunoscute (dacă veţi include cuvinte între ghilimele, interpretorul va efectua substituţii). • Exemplu: %puts {În şirul´hello´ sunt [string lenght hello] caractere}; În şirul ´hello´, sunt [string lenght hello] caractere Interpretorul Tcl, va transmite totul nemodificat. • Se utiliz. acoladele ca mecanism de grupare atunci când trebuie să transmiteţi anumite expresii unor comenzi de control, cum sunt ciclurile while şi for sau unor proceduri.
Variabile • În Tcl, orice entitate este, în mod prestabilit, un şir de caractere. Numele variabilelor, precum şi valorile acestora, sunt memorate ca şiruri de caractere. Pentru definirea unei variabile, utilizaţi comanda set. • Exemplu: Următoarele comenzi, definesc variabila carte cu valoarea ” Totul despre Linux, ediţia a noua” variabila an cu valoarea 2009 şi variabila preţ cu valoarea $49. 99: set carte ”Totul despre Linux, ediţia a noua” set an 2009 set preţ $49. 99 • Pentru a face referinţă la valoarea unei variabile, precedaţi numele acesteia cu semnul „dolar” ($). În consecinţă, pentru a afişa valoarea variabilei carte, vom utiliza comanda: %puts $carte Totul despre Linux, ediţia a noua • Dacă veţi utiliza comanda set cu un singur argument, acesta va returna valoarea argumentului respectiv. Comanda set carte este deci echivalentă cu $carte, după cum puteţi vedea şi din exemplul următor: %puts [set carte] Totul despre Linux, ediţia a noua
Expresii • Expresiile sunt generate prin combinarea variabilelor utilizând operatori matematici, care sunt + (adunare), - (scădere), * (înmulţire), / (împărţire). Exemple de expresii: set count 1 $count + 5 – 2 2 + 3. 5 • În cadrul expresiilor, se pot utiliza atât nume cât şi numere. Pentru a facilita citirea expresiilor, utilizaţi o spaţiere corespunzătoare. Pentru a stabili ordinea de evaluare a expresiilor, recurgeţi la paranteze. Pe lângă operatorii aritmetici de bază, în Tcl sunt incluse şi anumite funcţii matematice, cum ar fi sin, cos, tan, log, şi sqrt. Aceste funcţii pot fi apelate exact la fel ca şi în C, cu argumentele în paranteze, ca în exemplul următor: set angle 1. 5 2*sin($angle) • Operatorii logici: | (negaţia), && (conjuncţia) şi || (disjuncţia). • Operatori de comparaţie: < (mai mic), > ( mai mare), <= (mai mic sau egal), == (egal) şi != (diferit de). • Expresiile care utilizează operatorii de comparaţie sau operatori logici cu valoarea 1, dacă sunt adevărate, respectiv 0, dacă sunt false.
• Două expresii corect formate sunt următoarele: count == 10 angle < 3. 1415 • Expresiile nu reprezintă comenzile propriu-zise. Acestea pot fi însă transmise ca argumente, dar numai către comenzi care acceptă expresii ca argumente. Două exemple binecunoscute de comenzi sunt if şi while. În Tcl, o expresie poate fi evaluată utilizând comanda expr. • Exemplul următor vă arată cum puteţi evalua o expresie în interiorul unei comenzi Tcl: %set angle 1. 5 %puts 'Rezultat = [expr 2*sin($angle)]' Rezultat=1. 99499
Comenzi de control al fluxului. • Comenzile de control al fluxului din limbajul Tcl permit să se precizeze ordinea în care interpretorul limbajului va executa comenzile. Comanda if are o sintaxă de forma: if {expresie} { Secv_comanda } [elseif expresie}{ Secv_comanda. . . } elseif expresie } { Secv_comanda ] }[ else { Secv_comanda }] Acest mod de utilizare a acoladelor trebuie respectat cu stricteţe în script-urile Tcl. Între numele comenzii de control (if) şi acolada de deschidere ({)care urmează după acest nume trebuie lăsat un spaţiu. Efectul comenzii if este similar celui descris în Bash.
• Exemplu: if {$error. Count > 25 }{ puts ”Prea multe erori!” } • Puteţi adăuga la această formă şi o clauză else, pentru cazul în care expresia este evaluată la zero (fals). • Exemplu: if {$user == 'root'} { puts ”Configurarea sistemului a fost lansata. . . ” } else { puts ”Ne pare rău, trebuie să rulaţi acest program ”root!” }
• Comanda if din Tcl poate fi urmată de zero sau mai multe comenzi elseif, necesare pentru efectuarea unor teste ceva mai complexe, ca în exemplul următor: if {$version >= 10}{ puts ”Nu este necesară o actualizare” }elseif {$version >= 6 && $version <= 9}{ puts ”Efectuaţi actualizarea standard” }elseif {$version >= 3 && $version < 6}{ puts ”Trebuie să reinstalaţi complet sistemul” }else{puts ”Ne pare rău, nu putem efectua actualizarea” }
• Comanda while execută un bloc de comenzi până când o anumită expresie devine falsă. • Exemplu. Ciclul while următor citeşte linii de la intrarea standard până când utilizatorul apasă secvenţa Ctrl+D: while {[gets stdin line] != -1}{ puts $line #Alte prelucrări asupra valorii $line} • Observăm că între acolade se găsesc de fapt două argumente. Primul este chiar expresia, cel de-al doilea conţine comenzile Tcl care vor fi executate dacă expresia este adevărată. Pentru a delimita ambele argumente, trebuie să utilizaţi întotdeauna acoladele. Acestea au rolul de a împiedica interpretorul limbajului Tcl să evalueze conţinutul; ceea ce se află în interiorul acoladelor va fi interpretat de comanda while.
• Exemplu: Adunarea numerelor de la 10, cu excepţia lui 5. #!/usr/bin/tclsh set i 0 set sum 0 while {1}{incr i ; #incrementăm i if {$i==5}{continue}; #fdacă i este 5, nu #adunăm valoarea if {$i>10}{break}; #dacă i depăşeşte 10, # se iese din cliclu set sum [expr $sum+$i]; #altfel, adaugă i #la sum} } puts ”Sum = $sum”; • Atunci când într-un ciclu while utilizaţi o variabilă cu rol de contor, puteţi utiliza comanda incr pentru a incrementa acea variabilă. Puteţi „sări” direct la sfârşitul unei iteratii utilizând comanda continue; comanda break determină ieşirea din ciclu.
• Comanda for are în limbajul Tcl patru argumente şi trebuie scrisă în modul următor: for {expr_1}{expr_2}{expr_3}{ <comenzi> } • Comanda for evaluează expresia {expr_1} o singură dată, la începutul ciclului, executând apoi comenzile cuprinse în ultima pereche de acolade până când valoarea expresiei {expr_2} devine zero. Comanda for evaluează expresia {expr_3} după fiecare execuţie a comenzilor din corpul ciclului. Oricare dintre cele trei expresii poate lipsi, dar nu trebuie să omiteţi acoladele. • Exemplu: Se utiliz. un ciclu for pentru a aduna numerele de la 10: #!/usr/bin/tclsh for {set i 0; set sum 0}{$i<=10}{set sum [expr $sum+$i}; incr i{} puts ”Sum = $sum”;
• Comanda foreach. Această comandă nu are echivalent direct în limbajul C, fiind însă extrem de utilă atunci când doriţi să executaţi o anumită operaţie asupra fiecărei valori dintr-o listă de variabile. În exemplul următor, se adună o listă de numere utilizând o comandă foreach: set sum 0 foreach i {1 2 3 4 5 6 7 8 9 10}{ set sum [expr $sum+$i] } puts ”Sum = $sum” • Dacă o listă este memorată într-o variabilă, puteţi utiliza numele acelei variabile în locul listei cuprinse în prima pereche de paranteze. În exemplul următor, ciclul foreach afişează şirurile de caractere dintr-o listă dată: set users ”root naba baba” foreach users $users{ puts ” $user” }
• Comanda switch din Tcl diferă semnificativ de instrucţiunea switch din C. În locul evaluării unei expresii aritmetice, comanda switch din Tcl compară un şir de caractere cu un set de modele, executând un anumit set de comenzi, în funcţie de modelul care se potriveşte cu şirul. Modelul este de obicei exprimat sub formă de expresie regulată. Sintaxa şi modul de utilizare a comenzii switch sunt ilustrate prin următorul exemplu: #!/usr/bin/tclsh #Acest script citeşte comenzile introduse de utilizator # şi le prelucrează utilizând o comandă switch set prompt ”Introduceţi comanda (”quit”) pentru ieşire): ” puts –nonewline ”$prompt”; flush stdout while {[gets stdin cmd] != -1}{ switch –exact --$cmd{ quit {puts ”Bye!”; exit} Start {puts ”Started”} Stop {puts ”Stopped”} draw {puts ”Draw. . . ”} default {puts ”Comanda necunoscuta: $cmd} } #interogheaza din nou utilizatorul puts –nonewline $prompt; flush stdout }
Introduceti comanda (”quit”)pentru iesire): help Comanda necunoscuta: help Introduceti comanda (”quit”)pentru iesire): start Started Introduceti comanda (”quit”)pentru iesire): stop Stopped Introduceti comanda (”quit”)pentru iesire): quit Bye! • Comanda switch compară un şir de caractere cu o mulţime de modele, după care execută un set de comenzi, în funcţie de modelul cu care a detectat echivalenţa. În exemplul de mai sus, şirul de caractere comparat este $cmd (care este iniţializat prin citirea comenzilor introduse de utilizator folosind o comandă gets), iar şabloanele sunt şirurile quit, start, stop şi draw. Indicatorul –exact din forma generală a comenzii switch forţează detectarea echivalenţei exacte: Switch –exact -- $cmd{. . . }
• Cele două liniuţe (--) de după opţiunea –exact marchează sfârşitul opţiunilor comenzii switch. Nu omiteţi niciodată aceste două liniuţe de la sfârşitul secţiunii de comenzi, pentru a împiedica echivalenţele accidentale dintre şirul de test şi un indicator (flag). • Pentru compararea şirului de test cu una sau mai multe expresii regulate, utilizaţi comanda switch cu opţiunea –regexp, ca în exemplul următor: #Presupunem ca sirul de test este $cmd switch -regexp --$cmd{ ^q. *{puts ”Bye!”; exit} ^x. *{puts ”Optiunea x. . . ”} ^y. *{puts ”Optiunea y. . . ”} ^z. *{puts ”Optiunea z. . . ”} default {puts ”Comanda necunoscuta: $cmd”} } • În acest exemplu, toate expresiile regulate au aceeaşi formă. Modelul ^z. * desemnează toate şirurile care încep cu o singură literă z, urmată de un număr nedefinit de alte caractere.
Proceduri în Tcl • Se utiliz. comanda proc pentru a crea propriile comenzi. Aceste comenzi sunt denumite proceduri; interpretorul limbajului Tcl le tratează nediferenţiat faţă de comenzile Tcl native. Sintaxa unei declaraţii de procedură este: proc nume lista_arg corp_proc nume este identificatorul procedurii; lista_arg este o listă a parametrilor proceduri; corp_proc este o listă de comenzi tcl. • Exemplu. proc Diag {a b} { set c [expr sqrt($a * $a + $b * $b)] return $c } puts "Diagonala unui triunghi dreptunghic cu catetele de lg. 3 si 4 este [Diag 3 4]" Diagonala unui triunghi dreptunghic cu catetele de lg. 3 si 4 este 5
• Exemplu: #!/usr/bin/tclsh proc total items{ set sum 0 foreach I $items { set sum [expr $sum+$I] } return $sum } set counts “ 5 4 3 5” puts “Total =[total $counts]” • În acest exemplu, numele procedurii este total; aceasta primeşte ca argument o listă de numere. Procedura citeşte lista în variabila numită items. Corpul procedurii extrage fiecare element din listă şi returnează suma tuturor elementelor. Prin urmare, pentru a aduna numerele de la 10, puteţi apela procedura total ca în exemplul următor: set sum 1_10 [total {1 2 3 4 5 6 7 8 9 10}]
• Într-o procedură Tcl, argumentul args are o semnificaţie specială: utilizând acest argument puteţi trimite procedurii un număr variabil de argumente. Redenumind argumentul items al procedurii args, veţi putea ulterior apela procedura total în modul următor: set sum 1_10 [total 1 2 3 4 5 6 7 8 9 10]; #remarcati numarul variabil de argumente • Pentru a avea access la o variabilă globală (definită în afara procedurii) în procedura Tcl, trebuie să utilizaţi comanda global în interiorul procedurii. Această comandă determină ca o variabilă globală să devină vizibilă în interiorul domeniului de valabilitate al unei proceduri. Spre exemplu, dacă modalitatea curentă de desenare dintr-un program Tk (setul de instrumente X din Tcl) este memorată în variabila the. Canvas, pentru a utiliza aceeaşi zonă într-o procedură, în corpul procedurii trebuie să includem comanda: global the. Canvas
Lucrul cu şiruri de caractere în Tcl • Comenzile Tcl append, join, split, string, regexp şi regsub operează asupra şirurilor de caractere. Atunci când atribuim unei variabile un şir de caractere, interpretorul limbajului Tcl îl consideră ca pe o entitate de sine stătătoare, chiar dacă include spaţii sau caractere speciale. În unele situaţii, trebuie să despărţm un şir de caractere într-o listă de elemente. Separarea unui şir de caractere în componente se realizează cu comanda split. Comanda split are sintaxa: split sir car_sep în care: sir este şirul de caractere care vrem să-l împărţim în componente ale unei liste; car_sep reprezintă caracterul(ele) utilizat ca separator(ri). • Exemplu. set şir “ 1, 2. 2, a. b, c, abc” set lista 1 [ split $sir , ] separatorul este caracterul , ; lista 1 va conţine 1 2. 2 a. b c abc set lista 2 [ split $sir {, . }] Vom avea două caractere de separare , . ; lista 2 va conţine 1 2 2 a b c abc set lista 3 [ split $sir {}] separatorul este caracterul vid. lista 3 va conţine: 1 , 2. 2 a. b , c , a b c
• Comanda join realizează operaţia inversă lui split; această comandă crează un singur şir de caractere prin concatenarea elementelor unei liste. • Exemplu. Să presupunem că avem o listă cu şase elemente, definită astfel: set x {1 2 3 4 5 6} • La concatenarea elementelor dintr-o listă, putem selecta caracterul prin care vor fi despărţite câmpurile. Pentru a concatena elementele din listă fără a introduce nici un caracter între ele, utilizăm: set y [join $x ””] • În urma execuţiei acestei comenzi, şirul de caractere y va avea valoarea ” 123456”.
• string reprezintă un grup de comenzi care lucrează cu şiruri de caractere, primul argument al comenzii precizând operaţia care va fi executată. • De exemplu, comanda string compare realizează comparaţia a două şiruri de caractere, returnând zero atunci când cele două şiruri sunt identice. • Dacă valoarea întoarsă este – 1, atunci primul parametru este mai mic decât al doilea (ordinea lexicografică). Reciproc, dacă funcţia returnează valoarea 1, înseamnă că primul şir este mai mare decât cel de-al doilea. • Exemplu. Utilizarea comenzii string compare în cadrul unei comenzi if. if {[string compare $command “quit” ==0}{ puts “Exiting. . . ” exit 0 }
• • Tablouri În Tcl, un tablou este o variabilă cu un index de tip şir de caractere. Un tablou conţine elemente; indexul fiecărui element se numeşte numele elementului. Cu alte cuvinte, puteţi avea acces la orice element al tabloului prin intermediul numelui acestuia. Intern, tablourilor sunt implementate utilizând o structură de date extrem de eficientă, numită tabela de dispersie(hash), care permite interpretorului Tcl să găsească orice element al tabloului într-un timp aproximativ constant. Declararea unui tablou se realizează utilizând comanda set. În exemplul următor, am definit un tablou numit disk_usage, care conţine spaţiul ocupat pe disc de fiecare din utilizatorii sistemului: set disk_usage(root) 147178 set disk_usage(naba) 28574 set disk_usage(emily)55 set disk_usage(ivy) 60 După ce aţi definit un tablou, puteţi avea acces la elementele acestuia prin intermediul numelor, ca în exemplul următor: set user ”ilflorea” puts ”Spatiul pe disc utilizat de $user = $disk_usage($user)k”
Lucrul cu fişiere în Tcl • Majoritatea exemplelor prezentate până acum în acest capitol recurg la comanda puts a limbajului Tcl pentru afişarea rezultatelor. • puts scrie la ieşirea standard( fereastra xterm, în mediul X). • Puteţi scrie rezultatele într-un fişier furnizând identificatorul fişierului ca prim argument al comenzii puts. (fişierul trebuie să fie mai întâi deschis cu comanda open). • Exemplu: vom deschide un fişier, vom scrie o linie şi îl vom închide: set fid [open “testfile” w]; #deschidem #fisierul numit testfile pentru scriere puts $fid “Test 1. . 2. . 3”; #utilizam #identif. fisiserului ca parametru al lui #puts pentru a scrie in fisier close $fid •
• La afişarea unui şir de caractere la ieşirea standard, nu trebuie să specificaţi nici un identificator de fişier. Comanda puts va adăuga la sfârşitul fiecărui fişier un caracter linie nouă. • Dacă nu doriţi ca la sfârşitul unui şir să fie adăugat acest caracter, utilizaţi comanda puts cu argumentul – nonewline, ca în exemplul următor: puts –nonweline “Comanda> “; #Optiunea –nonwline se #utilizeaza la afisarea proptului de comanda flush stdout; #ne asiguram ca rezultatul este #imediat afisat • Pentru a citi de la intrarea standard, am utilizat comanda gets. • Exemplu: Citirea unei linie de la intrarea standard (comanda îşi încheie execuţia la apăsarea tastei Enter): set line [gets stdin]; #citeste o linie de la intr stand.
• Cuvântul cheie stdin reprezintă un identificator de fişier predefinit asociat intrării standard, în mod prestabilit tastatura. Alte identificatoare predefinite sunt stdout, pentru ieşirea standard şi stderr, ca dispozitiv standard de afişare a erorilor. În mod prestabilit, atât stdout cât şi stderr sunt conectate la ecranul calculatorului. • Exemplu: prezentăm o modalitate diferită de apel a funcţiei gets, pentru citirea unei linii într-o variabilă numită line: gets stdin line ; #citeste o linie in variab. #numita line • Pentru citirea dintr-un alt fişier, trebuie mai întâi să deschideţi acel fişier pentru citire, după care transmiteţi identificatorul fişierului ca argument pentru gets. Pentru citirea tuturor liniilor din fişierul /etc/passwd şi afişarea lor la ieşirea standard, putem proceda ca în exemplul următor: set fpass [open “/etc/passwd” r]; #deschidem #fisierul /etc/passwd pentru citire while{[gets $fpass line]!=-1}{; #citim toate #linile intr-un ciclu while puts $line ; #afisam fiecare linie in parte }
• Comanda gets este utilă la citirea fişierelor text, deoarece prelucrează o singură linie la un moment dat. De fapt, comanda caută caracterul linie nouă ca un marcaj care indică sfârşitul unei linii de text. Atunci când trebuie să citim date în format binar, trebuie să utilizăm comanda read în locul lui gets. • Exemplu: Pentru citirea şi prelucrarea unui fişier în incremente cu lungimea de 2048 de octeţi, vom utiliza comanda read în următorul mod: #Presupunem ca fid reprezinta # identificatorul unui fisier deschis while{![eof $fid]} ; {#pana la sfarsitul # fisierului set buffer[read $fid 2048] ; #citeste in buffer 2048 de octeti #prelucreza informatia din buffer }
• Al doilea parametru al comenzii read este numărul maxim de octeţi care vor fi citiţi. Dacă omiteţi acest parametru, comanda read va citi întregul fişier. Puteţi utiliza comanda read în acest mod pentru a citi şi prelucra dintr-o singură parcurgere un întreg fişier text. După ce aţi citit conţinutul fişierului, utilizaţi comanda split pentru separarea datelor în linii de text. • Exemplu: set fid[open “etc/passwd” r]; #deschide fis. Ptr. # citire set buffer [read $fid 100000]; #citeste intreg fis # in buffer split $buffer “n” ; #desparte bufferul in linii foreach line $buffer{ puts $line ; #prelucreaza linia }
• Dacă doriţi să prelucraţi mai multe fişiere (de exemplu, toate fişierele cu extensia. tcl), utilizaţi comanda glob pentru expandarea unui nume generic de forma *. tcl într-o listă. Puteţi apoi utiliza comanda open pentru deschiderea şi prelucrarea fiecărui fişier, astfel: foreach filename [glob *. tcl]{; #utilizam #comanda glob pentru a crea lista numelor # fisierelor puts –nonewline $filename ; #afisam numele fisierului #(doar pentru text) set file [open $fielname r] ; #deschidem fisierul gets $file line ; #citim prima linie puts $line ; #tiparim linia(doar pentru text) #prelucrari asupra restului fisierului (daca este # cazul) close $file ; #inchidem fisierul } • Acest exemplu ilustrează modul în care putem utiliza comanda glob într-un script.
• • • Execuţia comenzilor sistemului Linux. Pentru a nu reproduce inutil numărul mare de comenzi Linux, limbajul Tcl oferă un mecanism prin care puteţi rula orice comandă Linux. Cunoscând comenzile Linux, le puteţi utiliza direct în scripturile Tcl. Pentru a executa o comandă Linux într-un script Tcl, se utilizează comanda exec. În forma cea mai simplă, comanda exec preia ca argument numai comanda Linux. De exemplu, pentru a afişa conţinutul directorului curent, tastaţi comanda: exec ls Rezultatul acesteia va apărea la ieşirea standard (pe ecran), adică exact ca atunci când introduceţi comanda direct de la promptul interpretorului. La rularea comenzilor Linux din interpretor, puteţi redirecta intrarea şi ieşirea utilizând anumite caractere speciale, cum sunt < (pentru redirectarea intrării), > (pentru redirectarea ieşirii) şi | (pipe). Aceste opţiuni rămân valabile şi în Tcl, deoarece comanda exec acceptă linii întregi de comandă, care conţin inclusiv redirectări ale intrării şi ieşirii.
• Exemplu: Pentru a memora conţinutul directorului curent în fişierul numit dirlist, putem utiliza comanda: exec ls >dirlist • Comanda exec din Tcl nu efectuează expandarea caracterelor speciale (cum sunt asteriscurile) din numele fişierelor pe care le transmiteţi unei comenzi Linux. Pentru a utiliza asteriscuri, trebuie să efectuaţi o operaţie în plus: prelucrarea expresiei care specifică numele fişierelor cu ajutorul comenzii glob, pentru efectuarea corectă a expandării înainte de a transmite comanda ca argument pentru exec. Mai mult, întreaga comanda exec trebuie trimisă ca argumant al unei comenzi eval. • Exemplu: Afişarea listei tuturor fişierelor cu extensia. tcl, utilizând comanda exec cu glob şi transmiterea întregul şir de comandă comenzii eval: eval exec ls [glob *. tcl] ; #echivalentul Linux al comenzii “ls *. tcl”
- Slides: 37