Administrare server open source

Platforma de hosting cu software liber, gratuit, open source.

Printre administratorii de sistem sau de retea e o moda sa cunosti cel putin un limbaj de scripting. De ce? Pentru ca flexibilitatea limbajelor de scripting usureaza foarte mult munca. Unul dintre limbajele de scripting cele mai folosite in UNIX e AWK si voi incerca sa fac o mica introducere in modul de utilizare a acestuia.

Ce este AWK?

AWK este un limbaj interpretat care ne usureaza munca. Numele lui vine de la initalele numelor autorilor ( Aho, Weinberger si Kernighan ). Punctul forte al acestui limbaj este usurinta cu care putem interpreta si prelucra textele putand foarte usor sa creem rapoarte, sa facem statistici si calcule matematice pe baza unui fisier text.
AWK poate fi folosit atat ca limbaj de scripting cat si ca si comanda.
Sa vedem cateva exemple care vor ajuta la formarea unei idei despre ce poate face acest limbaj.

a) Cautarea unui sir de caractere intr-un fisier text:
Folosim ca si exemplu fisierul /etc/passwd care este scris in text plan si cautam cuvantul ‘mail’. Cel mai simplu mod e sa facem asta din linia de comanda folosind urmatoarea sintaxa:

$ awk '/sir de cautat/' fisier.txt

In cazul nostru comanda si rezultatul sunt dupa cum urmeaza:

[email protected]$ awk '/mail/' /etc/passwd
smmsp:*:25:25:Sendmail Submission User:/var/spool/clientmqueue:/usr/sbin/nologin
mailnull:*:26:26:Sendmail Default User:/var/spool/mqueue:/usr/sbin/nologin
[email protected]$

Dupa cum vedeti AWK a parcurs fisierul /etc/passwd si a afisat liniile care contin cuvantul cautat, in cazul nostru cuvantul ‘mail’.

b) Cautarea unui sir si afisarea selectiva
Exemplul anterior nu arata nimic iesit din comun. E simplu de cautat un cuvant intr-un fisier in orice editor de texte care se respecta. Haideti sa vedem un exemplu mai complex in care nu ne mai putem folosi de un simplu editor de texte.
Pentru exemplificare folosesc un fisier, ip.txt, care tine datele in format TSV (Tab Separated Values). Fisierul are urmatorul continut:

33996344        33996351        GB      GBR     UNITED KINGDOM
50331648        69956103        US      USA     UNITED STATES
69956104        69956111        BM      BMU     BERMUDA
69956112        83886079        US      USA     UNITED STATES
94585424        94585439        SE      SWE     SWEDEN
100663296       121195295       US      USA     UNITED STATES
121195296       121195327       IT      ITA     ITALY
121195328       152305663       US      USA     UNITED STATES
152305664       152338431       GB      GBR     UNITED KINGDOM
152338432       167772159       US      USA     UNITED STATES
184549376       201674095       US      USA     UNITED STATES
201674096       201674111       CA      CAN     CANADA

Probabil unora vi se pare cunoscut fisierul. Pentru cei care nu stiti ce sunt liniile de mai sus, e vorba de o parte dintr-un fisier mai mare care contine IP-urile alocate fiecarei tari.
Bun, revenind la exemplul nostru, ne intereseaza grupurile de IP-uri corespunzatoare statelor unite. Cum ne poatem usura treaba folosind awk? Simplu, ii „spunem” ce anume sa caute ca in exemplul precedent:

[email protected]$ awk '/UNITED STATES/' ip.txt
50331648        69956103        US      USA     UNITED STATES
69956112        83886079        US      USA     UNITED STATES
100663296       121195295       US      USA     UNITED STATES
121195328       152305663       US      USA     UNITED STATES
152338432       167772159       US      USA     UNITED STATES
184549376       201674095       US      USA     UNITED STATES
[email protected]$

Nimic deosebit fata de celalalt exemplu, nu? OK, acum ne-am „prins” cum se pot selecta liniile corespunzatoare statelor unite, dar pe noi ne intereseaza doar primele doua coloane si nimic mai mult. Nu e nici o problema. Extindem putin comanda si din awk ‘/UNITED STATES/’ ip.txt o transformam in awk ‘/UNITED STATES/ {print $1,$2}’ ip.txt. Rezultatul afisat va fi dupa cum urmeaza:

[email protected]$ awk '/UNITED STATES/ {print $1,$2}' ip.txt
50331648 69956103
69956112 83886079
100663296 121195295
121195328 152305663
152338432 167772159
184549376 201674095
[email protected]$

Ce s-a intamplat, de fapt? awk a cautat in fisierul ip.txt toate liniile care contineau sirul de caractere ‘UNITED STATES’ iar apoi pentru fiecare linie gasita a aplicat regula {print $1,$2} care ii spune sa afiseze doar coloana 1 si 2. Dupa cum v-ati prins, cu simbolul dolar se specifica coloana care ne intereseaza. Daca ne interesau doar coloanele 3 si 4 foloseam in loc de {print $1,$2}, {print $3,$4} iar rezultatul afisat era format din 6 linii de forma: US USA.
De mentionat ca puteam lasa print fara nici un parametru dupa, adica doar {print}, caz in care era afisata intreaga linie ca si in primul exemplu dat. Acelasi lucru se intampla si daca ii spuneam interpretorului sa afiseze doar $0, pentru ca $0 retine intreaga linie citita.

Bun, am vazut cum se poate restrange rezultatul dar daca ne intereseaza sa punem conditii inainte de afisarea sau prelucrarea unei linii? Se poate si asta. In exemplul de mai sus sa presupunem ca ne intereseaza doar liniile care au pe prima coloana o valoare mai mica de 100000000. E la fel de simplu ca pana acum. Adaugam o simpla conditie, un if cu care probabil majoritatea sunteti obisnuiti din alte limbaje de programare/scripting. Codul de mai sus se transforma in awk ‘{ if($1<100000000) print $0}’ ip.txt iar exemplul practic e urmatorul:

[email protected]$ awk '{ if($1<100000000) print $0}' ip.txt
33996344        33996351        GB      GBR     UNITED KINGDOM
50331648        69956103        US      USA     UNITED STATES
69956104        69956111        BM      BMU     BERMUDA
69956112        83886079        US      USA     UNITED STATES
94585424        94585439        SE      SWE     SWEDEN
[email protected]$

Dupa cum se vede, conditia a fost aplicata cu succes si toate liniile care au pe prima coloana o valoare mai mica de 100000000 sunt afisate. Daca ne interesau doar rezultatele din statele unite, putem adauga din nou criteriul de sortare dupa cum am fost obisnuiti din exemplele anterioare:

[email protected]$ awk '/UNITED STATES/ { if($1<100000000) print $0}' ip.txt
50331648        69956103        US      USA     UNITED STATES
69956112        83886079        US      USA     UNITED STATES
[email protected]$

c) Contorizarea

Un alt exemplu de utilizare awk este contorizarea numarului de linii prezente intr-un fisier, functionalitate foarte utila in cazul generarii unor rapoarte. Sa ramanem la fisierul din exemplul anterior si sa vedem cum putem afla numarul de linii din fisier. Problema se rezolva in felul urmator:

[email protected]$ awk 'END {print NR}' ip.txt
12
[email protected]$

Da… e simplu. Am folosit END care este un termen nou si care merita putina atentie. Normal, un script AWK sau o comanda arata in felul urmator:

awk 'BEGIN
    primul_criteriu_de_cautare      {actiunile aplicate}
    al_doilea_criteriu_de_cautare   {actiunile aplicate}
    al_treilea_criteriu_de_cautare  {actiunile aplicate}
    al_patrulea_criteriu_de_cautare {actiunile aplicate}
    END {actiunile aplicate}'

Ce intelegem din asta? Un script e delimitat in mod normal de BEGIN care ne spune unde incepe scriptul si END care ne arata finalul scriptului. In exemplele de mai sus nu am folosit aceste doia cuvinte cheie pentru ca am folosit un singur criteriu de cautare si o actiune asociata caz in care BEGIN si END nu e obligatoriu sa apara.
Dupa cum va puteti da seama din exemplul de mai sus, intre BEGIN si END sunt puse mai multe linii, pe fiecare linie e specificat un criteriu de cautare/parcurgere a textului si un set de actiuni care se aplica liniilor gasite cu ajutorul criteriului specificat. Scriptul se termina la END, putand specifica de asemenea niste actiuni finale, actiuni care sunt specificate doar inainte de finalizarea comenzii.
Astfel, ca sa intelegeti ce exemplul de contorizare de mai sus, interpretorului i se da doar actiunea de final, actiunea care ia loc la finalizarea scriptului (de aici cuvantul END in comanda).
Ce inseamna awk ‘END {print NR}’ ip.txt? Interpretorul ia fiecare linie din ip.txt si verifica daca corespune cu o conditie data (in cazul nostru nici una) iar cand toate liniile au fost parcurse se aplica conditia de final, conditia de dupa END care in cazul nostru este {print NR}. NR este o valoare care se incrementeaza la fiecare linie citita de interpretor. Astfel, interpretorul citeste fisierul ip.txt si nu face nimic decat la sfarsit cand afiseaza valoarea NR care ne arata numarul de linii citite.

Probabil v-ati dat seama deja ca si rezultatul afisat poate fi personalizat. De exemplu, putem inlocui {print NR} cu {print NR,” linii citite”}, adica adaugam inca un sir de caractere care trebuie afisat, de data asta un sir constant de caractere nu o variabila sau constanta a programului. Rezultatul va fi urmatorul:

[email protected]$ awk 'END {print NR, " linii citite"}' ip.txt
12  linii citite
[email protected]$
Linux

3 Responses so far.

  1. Alex says:

    Salut,
    Foarte tare, chiar util… singurul comentariu ar mai fi legat de precizarea faptului ca e copy/paste dupa un articol din 2006

  2. Sergiu Tot says:

    Intr-adevar e un articol mai vechi, la fel ca alte cateva de pe site, dar articolul original e scris tot de mine. Daca te deranjeaza, ignora-l pe cel de aici si citeste-l doar pe cel de pe SkullBox 🙂

  3. Fanel says:

    foarte bun pentru incepatori.bravo