Fisiere de comenzi Unix
5.1 Generalitati despre programarea shellInterpretorul de comenzi al sistemului de operare Unix furnizeaza, pe langa posibilitatea de executare a comenzilor, un set de instructiuni care permite scrierea de programe asemanatoare celor scrise in limbaje de programare de nivel inalt. Fireste, posibilitatile acestui limbaj sunt mult mai slabe decat cele ale unui limbaj ca C ori Pascal, dar exista aplicatii in care efortul de programare este mult redus. Pe linga comenzile "obisnuite", care apar in orice sistem de operare, Unix furnizeaza si o multime de utilitare, mai ales pentru fisiere text. Limbajul Shell este puternic si eficient pentru:
Obiectele ce compun un script sunt:
Dupa cum ati observat, nu exista o instructiune de salt neconditionat (goto), programele capatand astfel lizibilitate. Introducerea instructiunilor repetitive permite scrierea de programe structurate, spre deosebire de "limbajul" batch din sistemul de operare MSDOS. Un script poate primi in linia de comanda argumente. De asemenea, se pot apela, din interiorul unui script, alte scripturi. Scripturile pot fi
scrise cu ajutorul unui editor de texte ca vi, ed, emacs. Apoi se
stabileste dreptul de executie a fisierului, numele sau putand fi folosit ca o
comanda obisnuita. Shell-ul va executa fisierul comanda cu comanda. pwd ls -l finger
5.2 Afisarea datelor. 747d33h ComentariiIntroducerea de comentariiDe cele mai multe ori,
la inceputul programului, trebuie sa precizam care este efectul acestuia,
pentru ca nu este intotdeauna evident acest lucru (s-ar putea ca pe unii
utilizatori sa nu-i intereseze cum lucreaza scriptul ci doar ce
face acesta). La inceputul programului trebuie precizat sub ce interpretor a
fost scris. De exemplu, comanda speciala #!/bin/sh indica faptul ca
instructiunile care urmeaza trebuie interpretate de Bourne Shell. Proceduri de citire/scriereAfisarea informatiilor
se face cu ajutorul comenzii echo a carei sintaxa este:
Pentru a se tine cont
de caracterele speciale ce apar in sirurile de caractere date ca argumente,
trebuie folosita optiunea -e, de exemplu: Luni Marti
5.3 VariabileVariabile definite de utilizatorNumele variabilelor definite de utilizator trebuie sa respecte urmatoarele reguli:
Declararea unei
variabile se face implicit prin atribuirea unei valori (ca in BASIC). Comenzile: s="Azi e luni si\nincepe semestrul" echo -e $s afiseaza: azi e luni si incepe semestrul
Exista posibilitatea de a proteja o variabila la eventuale modificari accidentale, folosind comanda readonly (variabila). Dupa aceasta comanda, incercarea de a modifica valoarea variabilei determina aparitia unui mesaj de eroare. In cazul in care nu mai
stim numele tuturor variabilelor folosite, putem obtine lista variabilelor,
inclusiv valoarea actuala, prin comanda set. Aceasta lista contine nu
numai variabilele definite de utilizator ci si variabilele sistem. Presupunem ca s-au definit variabilele: a="Decat mult si fara rost" b="putin"c="prost" si s-a creat urmatorul script, in fisierul deviza: #!/bin/sh echo -e "$a mai bine $b si $c !\n" a="Ce mai faci ?\n" echo -e $aDaca se dau comenzile: hasdeu~$ export a b c hasdeu~$ deviza hasdeu~$ echo $ase va afisa : Decat mult si fara rost mai bine putin si prost ! Ce mai faci ? Decat mult si fara rostPutem defini explicit
variabile de tipul intreg prin comanda declare -i (var), incecarile
ulterioare de a da variabilei o valoare sir de caractere determinand obtinerea
valorii 0 pentru acea variabila.
declare -i n1 declare -i n2 n1=8 n2=6n1=n1+n2 #sau let n1=n1+n2 n2=n2%2 echo $n1 $n2
Variabile sistemFoarte multe utilitare
lucreaza cu variabile a caror valoare este predefinita si care sunt la
dispozitia tuturor utilizatorilor (le vom numi variabile sistem). De obicei,
variabilele sistem sunt scrise cu litere mari, pentru a le deosebi de variabilele
definite de utilizator. Modificarea valorii unei variabile sistem poate crea
neplaceri, deoarece utilitarele care folosesc valoarea variabilei vor lucra
defectuos !!!
Variabile speciale (predefinite)O categorie aparte de variabile sistem sunt cele predefinite, numite si variabile speciale. Ele sunt variabile readonly, initializate si actualizate doar de interpretor. Variabilele speciale sunt date in urmatorul tabel:
Valori returnateEste foarte important a se putea determina daca o comanda a fost executata cu succes sau nu. Fiecare comanda returneaza o valoare (exit status) memorata in variabila $?. Daca valoarea este 0 inseamna ca a aparut o eroare in cursul executiei ultimei comenzi si este nenula in caz contrar. Testul executiei cu succes se poate face cu ajutorul comenzii test, ce va fi prezentata ulterior. Parametri de pozitiePentru a putea furniza
si argumente in linia de comanda a unui script, se folosesc parametri de
pozitie, prin care sunt disponibile valorile acestora. Parametri de pozitie
sunt notati cu $1, $2,..., $9. $0 contine numele scriptului, $1 contine primul
parametru, $2 contine al doilea parametru e.t.c 5.4 Citirea datelor. Comanda readPentru a avea un contact direct cu utilizatorul, in afara folosirii parametrilor de pozitie, exista pozibilitatea de a se introduce date prin intermediul comenzii read.Datele citite sunt transmise pe canalul de intrare standard si memorate in variabilele pasate ca parametrii din comanda read. Sintaxa este urmatoarea: read (variabila)...
5.5 Verificarea unei conditii. Comanda testComanda test verifica indeplinirea unei conditii si intoarce o
valoare care sa marcheze acest lucru. Pentru a se cunoaste rezultatul testului, se foloseste variabila $?.
Aceasta are valoarea 0 daca testul este pozitiv (conditie adevarata) si o
valoare diferita de 0 in caz contrar.
Teste asupra fisierelorTestul asupra unui
fisier consta in verificarea daca acesta verifica o conditie specificata
printr-o optiune. Sintaxa generala este urmatoarea:
Comanda test poate fi combinata cu alte comenzi cu ajutorul operatorilor && si ||, formindu-se siruri de comenzi. Cea mai folosita combinatie este cea cu comanda echo: test -x doom
&& echo "Aveti drept de executie !!!" Teste asupra sirurilor de caractereExista doua tipuri de teste asupra sirurilor de caractere: test pentru a controla daca un sir de caractere este vid si test pentru a vedea daca doua siruri sunt identice. Pentru primul tip de test avem doua optiuni: test -z "variabila" (testeaza daca variabila contine un sir vid) test -n "variabila" (testeaza daca variabila contine un sir nevid)
A doua forma ne permite sa verificam daca doua siruri sunt sau nu identice, de exemplu: test "$a" = impozit verifica daca variabila $a are ca valoare sirul impozit. test "$f" != exitverifica daca variabila $f nu are valoarea exit
Teste numericePentru testele
numerice, comanda test trebuie sa aiba trei parametri:
Exemplu: x=10 y=6 test "$x" -ge "$y" && echo "$x mai mare ca $y"Scriptul verifica daca valoarea variabilei x este mai mare sau egala cu valoarea lui y siafiseaza mesajul corespunzator.
Exemple: Este posibila folosirea
parantezelor pentru a crea expresii complexe. Pentru a putea folosi
parantezele, acestea vor fi precedate de caracterul \, ca in exemplul de mai
jos: Forma restrinsa a comenzii testPentru a putea fi folosita mai usor in combinatie cu instructiunea if, comanda test are si o forma simplificata, in care numele comenzii este inlocuit de parantezele patrate [ si ]: [ -r lista ] este echivalenta cu test -r lista
5.6 Instructiunea ifMarele avantaj al limbajului de programare shell consta in existenta
structurilor de control al executiei instructiunilor. Instructiunea if
permite conditionarea executiei unei comenzi de indeplinirea unei conditii
logice. if (expresie logica) then (comanda)... [else (comanda)... ] fi unde: (expresie logica)- comanda sau suita de comenzi cu rezultat logic (comanda) - orice comanda acceptata de shell, inclusiv if
Instructiunea if functioneaza la fel ca instructiunile similare din limbajele Pascal si C. Cuvintele if, then, else si fi sunt cuvinte cheie. Este obligatoriu ca instructiunea if sa fie scrisa asa cum apare mai sus. EXEMPLE: 1. Scriptul urmator: if grep "Georgescu" lista > /dev/null then echo "Numele a fost gasit in lista " else echo "Numele nu este in lista " fi cauta
numele Georgescu in fisierul lista si afiseaza un mesaj in care se
precizeaza rezultatul cautarii. Dupa cum stiti (oare ?), comanda grep fara
optiuni afiseaza liniile care contin sablonul specificat. Prin redirectarea
iesirii (>/dev/null), se trimit liniile de text catre perifericul null
(trimitere catre "nicaieri"), pentru ca nu ne intereseaza liniile
gasite, ci doar daca exista asemenea linii. if grep "$1" "$2" >/dev/null then echo "$1 apare in fisierul $2" else echo "$1 nu apare in fisierul $2" fi
if [$# -lt 2] then echo "Prea putini parametri. Corect este: $0 sablon fisier" exit 1 fi if grep "$1" "$2" >/dev/null 2>&1 then echo "$1 apare in fisierul $2" else echo "$1 nu apare in fisierul $2"fi exit 0
5.7 Instructiunea casePentru deciziile multiple a fost implementata instructiunea case, care are urmatoarea sintaxa: case (valoare) in(sablon_1) (comanda)...;; (sablon_2) (comanda)...;; ... esac unde: (valoare) -"variabila" de selectie (sablon_i)-criteriu de cautare (domeniu de valori)(comanda) -orice comanda sau succesiune de comenzi acceptate de shell
Urmatorul script: case $LOGNAME inroot) PS1="#";; lucian | danut) PS1="Buna prietene $LOGNAME $";; *) PS1="Buna user obisnuit \h:\w\$ ";; esac export PS1 readonly PS1
5.8 Instructiunea forInstructiunea for se foloseste atunci cand un grup de comenzi trebuie executat de mai multe ori. Spre deosebire de instructiunea for din alte limbaje, in limbajul shell nu se fixeaza o limita inferioara si una superioara pentru variabila contor, aceasta luand valori dintr-o lista explicita de valori sau potivit unui anumit criteriu de cautare (in FOXPRO se intalneste o astfel de forma a instructiunii for). Sintaxa este: for (variabila) in (lista) do (comanda)... done
Folosirea listelor explicite de valoriO lista explicita este specificata prin enumerarea valorilor sale. Variabila contor va lua ca valoare, pe rand, fiecare valoare din lista: for fis in lista1 lista2 lista3 docat $fis rm -i $fis done
Liste construite dupa un anumit criteriuListele pot fi construite cu ajutorul simbolurilor folosite pentru scrierea numelor de fisier, referindu-ne la o multime de fisiere ce respecta un anumit criteriu. In exemplul urmator se vor afisa toate fisierele ce contin un text sursa C: for fis in *.c docat $fis done
Liste de valori impliciteLista de valori implicite este formata din lista parametrilor de pozitie, care este memorata variabila speciala $@. for fis in $@ dolpr $fis done care este echivalent cu: for fis dolpr $fis done 5.9 Instructiunea whileCiclul while este folosit pentru executia unei liste de comenzi atat timp cat este adevarata o anumita conditie. Sintaxa este urmatoarea: while (expresie logica) do (comanda)... done
echo -e "Introduceti numele fisierului: \c" read fis while [-z "$fis"]do echo "Eroare de introducere" echo -e "Introduceti numele fisierului: \c" read fis done
while true do ... done
5.10 Instructiunea untilCiclul until se termina atunci cand conditia devine adevarata. Sintaxa este: until (expresie logica) do (comanda)... done
5.11 Crearea meniurilor simple. Instructiunea selectSintaxa instructiunii select este: select (variabila) in (lista de valori) do (comanda)... done
Scriptul (sa presupunem, ca are numele exemplu): PS3="Introduceti un numar intre 1 si 3: " select optiune in matematica fizica informatica doif [ -n "$optiune" ] then echo "Materia preferata este $optiune" fi doneare urmatorul efect: hasdeu:~$ exemplu 1) matematica 2) fizica 3) informatica Introduceti un numar intre 1 si 3: 3 Materia preferata este informatica 1) matematica 2) fizica 3) informatica Introduceti un numar intre 1 si 3: ctrl+D hasdeu~$
5.12 Alte comenzi si chestii interesanteSubstitutia unei comenziShell-ul ne ofera posibilitatea de a substitui numele comenzilor cu numele dorite de utilizator. Sintaxa este urmatoarea: sir=$(suita de comenzi)
unde_sunt=$(pwd)
Definirea functiilorDefinirea unei functii se poate face din linia de comanda, scriind numele functiei si parantezele (). La intalnirea parantezelor, shell-ul asteapta introducerea acoladei deschise si a corpului functiei, iar in final acolada inchisa (semnificand terminarea definirii functiei). Sa definim o functie pentru listarea directoarelor date ca argumente, in forma lunga: hasdeu~$ listez ()
listez () sterg ()
5.13 Exemple de scripturi1. Scrieti un script care sa primeasca drept argument un nume de utilizator si sa afiseze daca acesta este conectat in sistem si cate sesiuni are deschise.
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||