Lucrarea 5

Utilitare soft Unix: grep,egrep,fgrep,awk

1. Scopul lucrãrii

Lucrarea de fata continua prezentarea ultimelor doua utilitare soft din sistemul de operare Unix: grep si awk.

2. Consideratii teoretice

2.1. Familia de programe GREP

Familia de programe grep ( Global Regular Expression Print) permite cãutarea unui sir, specificat printr-o expresie regulata, intr-o lista de fisiere. Rezultatul comenzii se poate afisa sau poate servi ca intrare pentru o alta comanda UNIX. Cele trei comenzi din familia grep sunt: grep, fgrep si egrep. Ele diferã prin generalitatea expresiei cãutate si prin viteza de cãutare. Comanda grep cautã expresii regulate specificate conform editorului ed, algoritmul de cãutare fiind compact si nedeterminist. Comanda fgrep ( Fast grep) cautã siruri fixe, algoritmul de cãutare fiind compact si rapid. Comanda egrep ( Extended Grep) cautã expresii regulate generalizate, algoritmul de cãutare fiind rapid si determinist.

In mod normal se foloseste fgrep pentru cãutarea sirurilor fixe si egrep in caz contrar, cu exceptia cãutãrilor de siruri ce se repeta când se foloseste grep. Expresiile regulate folosite de grep folosesc '\(' si '\)' pentru a defini grupuri, fiind permisa cãutarea de grupuri ce se repeta. In schimb expresiile regulate folosite de egrep nu folosesc simbolul '\' la definirea grupurilor si nu permit cãutarea de gupuri ce se repeta.

Sintaxa comenzilor:

grep [optiuni] sir [fisier(e)]

egrep [optiuni] [sir] [fisier(e)]

fgrep [optiuni] [sir] [fisier(e)]

Optiuni ce afecteazã cãutare :

-w Cãutarea se face pe cuvânt ( BSD Unix).

-v Selecteazã liniile care nu contin sirul.

-i Tratare echivalenta a literelor mari si mici.

Optiuni ce afecteazã iesirea:

-c Se indica doar numãrul de linii gãsite.

-l Se indica doar numele fisierelor ce contin sirul specificat.

-n Pentru fiecare linie se indica numele fisierului si numãrul liniei.

-s In versiunea V ( numai pentru grep) se suprima afisarea mesajelor de eroare.

Comenzile fgrep si egrep admit optiunile:

-e sir Se foloseste pentru cãutarea sirurilor ce încep cu '-'.

-f fis Se citeste lista de expresii regulate din fis.

Exemplu: fgrep "3242" studenti > gr3242

2.2. AWK

Analog utilitarului GREP, AWK este un instrument pentru analiza si manevrarea usoara si eleganta a datelor. Versiunea originala a fost dezvoltata in 1977 de cãtre Alfred Aho, Peter Weinberger, and Brian Kernighan de la AT&T Bell Labs. O versiunea îmbunãtãtitã este operationala din 1985. Gawk este implementarea GNU a awk-ului (disponibila sub Linux). Aceasta se considera a fi compatibila versiunea 4 de Unix System V. In cele ce urmeazã utilitarul awk este tratat in general fãrã particularitãti specifice unei versiuni. Din acest motiv se recomanda înainte de scrierea unui program awk consultarea bibliografiei aferente. Exemplele ilustrate au fost testate si executate atât sub Linux cat si sub Unix SVR4.

Un program AWK este format din mai multe comenzi. O comanda este formata la rândul ei dintr-un sablon de selectie si un bloc de actiune:

selectie { actiune }

Selectia se realizeazã prin folosirea expresiilor regulate. Actiunea are sintaxa apropiata C si permite efectuarea unor operatii pe datele din fisier. Un fisier este vãzut de un program awk ca fiind o succesiune de înregistrãri. Daca separatorul de înregistrare nu a fost modificat el având valoarea predefinitã, caracterul '\n', înregistrarea este identica cu linia. Înregistrarea este împãrtitã in câmpuri separatorul de câmpuri, FS, putând lua chiar si mai multe valori.

2.2.1. Sintaxa de apel

Setul de sabloane împreuna cu actiunile formeazã un program awk, care poate fi specificat in cadrul liniei de comanda sau poate fi pãstrat intr-un fisier, fiind citit ulterior de un program awk. Sintaxa:

awk -Fc [-f] <comanda_awk | program_awk> <fisier(e)>

c -reprezinta caracterul separator de câmpuri (implicit \t si \b) comanda_awk este o linie de forma 'selectie { actiune } '

program_awk (obligatoriu .awk) succesiune de comenzi awk.

fisier(e) - fisier(e) pe care se executa comanda sau comenzile awk. Fisierul standard de intrare se specifica prin '-'. Exemple de apeluri corecte:

$awk '$6 > $4' divizia1 divizia2

...

$awk '$1 > 0 { print $1, "; cu TVA: " $1*1.18 }'

123

123; cu TVA: 145.14

-98

Ctrl-D

$cat TVA.awk

$1 > 0 { print $1, "; cu TVA: " $1*1.18 }

$awk -f TVA.awk date.int # date.int = datele de intrare

2.2.2. Câmpuri si variabile

Fiecare înregistrare este impartita in câmpuri, functie de valoarea variabilei predefinite FS. Acestea sunt referite prin $1, $2, ...; $0 reprezita înregistrarea curenta. Exista urmatoarele variabile predefinite in programele AWK:

ARGC Numãrul argumentelor din linia de comanda.

ARGV Sirul argumentelor din linia de comanda. Sirul este indexat de la 0 la ARGC 1.

ENVIRON Sirul variabilelor din mediu. Sirul este indexat prin variabilele de mediu (de exemplu: ENVIRON["HOME"] poate fi /home/adi).

FILENAME Numele fisierului de intrare curent. Daca nu este specificat nici un fisier in linia de comanda, valoarea variabilei FILENAME este ''.

FNR (File Number Records) Numãrul inregistrarii curente citita din fisierul de intrare.

FS (Field Separator) Separatorul de câmpuri la intrare, implicit '\b'.

NF (Number of Fields) Numãrul de câmpuri din înregistrarea curenta.

NR (Number of Records) Numãrul de înregistrãri inspectate.

OFMT Formatul de iesire pentru numere, implicit "%.6g".

OFS (Output Field Separator) separatorul de câmpuri la iesire, implicit '\b'.

ORS (Output Record Separator) separatorul de înregistrare la iesire, implicit '\n'.

RS (Record Separator) separator de înregistrare, implicit '\n'. Daca RS este setat la sirul null, atunci inregistrarile sunt separate prin linii blanc. In acest caz, caracterul '\n' este separatorul de câmpuri, indiferent de valoarea lui FS.

RSTART Indexul primului caracter potrivit dintr-un apel al functiei match; 0 daca nu exista potrivire.

RLENGTH Lungimea sirului potrivit prin functia match; (1) in caz ca nu exista potrivire.

SUBSEP Caracterul folosit pentru a separa indici multipli la elemente de sir, implicit '\034'.

De exemplu:

#env.awk

BEGIN { for ( i in ENVIRON)

print i "=" ENVIRON[i]

}

$awk -f env.awk

LOGNAME=root

SHELL=/bin/bash

HOSTNAME=local.lab_a25.upg-ploiesti.ro

...

$awk '{ print NF, $1, $(NF-1), $NF }' divizia

8 Munchen 34000 Spectatori

8 Leverkusen 28000 Spectatori

8 HSV 29000 Spectatori

8 Stuttgart 25000 Spectatori

8 Bremen 30000 Spectatori

8 Frankfurt 27000 Spectatori

$awk '{ print "Jocul:", NR, $1, $2, $3 }' divizia

Jocul: 1 Munchen Sportul

Jocul: 2 Leverkusen Steaua

Jocul: 3 HSV Dinamo

Jocul: 4 Stuttgart U.Cluj

Jocul: 5 Bremen Politehnica

Jocul: 6 Frankfurt Dortmund

Variabilele utilizator din programele awk nu trebuie declarate, ele fiind declarate si initializate la prima folosire ( cu 0 variabilele numerice si cu "" variabile de tip sir de caractere). Valorile lor pot fi numere sau siruri, sau ambele, in functie de folosirea lor. De exemplu:

# ex1.awk - aflarea numarului de victorii in deplasare.

$6 > $4 { depl = depl + 1 }

END { print depl, "victorie(i) in deplasare"

$awk f ex1.awk divizia

1 victorie(i) in deplasare

# ex2.awk - raport final asupra meciurilor din etapa anterioara.

{ sum = sum + $7 } 
END { print NR, "Jocuri " 
print "Nr.total spectatori: ", sum 
print "Media pe meci: ", sum/NR 
} 
 

$awk f ex2.awk divizia

6 Jocuri

Nr.total spectatori: 173000

Media pe meci: 28833.3

2.2.3. Concatenarea sirurilor

Concatenarea de siruri se poate evidentia pe urmatorul exemplu:

# ex3.awk - echipele care au pierdut

BEGIN { print "Urmatoarele echipe au pierdut: " }

$4 > $6 { list = list $3 ", " }

END { print list }

$awk f ex3.awk divizia

Urmatoarele echipe au pierdut:

Sportul, Steaua, Politehnica,

2.2.4. Formatarea iesirii

Formatarea iesirii se poate observa pe exemplele:

$awk {printf("%20s: %6d Spectatori; %2d goluri\n", $1, $7, $4+$6) } divizia

Munchen : 34000 Spectatori; 5 goluri

Leverkusen : 28000 Spectatori; 3 goluri

HSV : 29000 Spectatori; 4 goluri

Stuttgart : 25000 Spectatori; 1 goluri

Bremen : 30000 Spectatori; 3 goluri

Frankfurt : 27000 Spectatori; 0 goluri

$awk '{ printf("%s a jucat contra %s scor final:%2d:%2d\n",

$1, $3, $4, $6) }' divizia

Munchen a jucat contra Sportul scor final: 3: 2

Leverkusen a jucat contra Steaua scor final: 2: 1

HSV a jucat contra Dinamo scor final: 2: 2

Stuttgart a jucat contra U.Cluj scor final: 0: 1

Bremen a jucat contra Politehnica scor final: 2: 1

Frankfurt a jucat contra Dortmund scor final: 0: 0

AWK permite siruri unidimensionale cele multidimensionale putând fi simulate. Sirurile sunt indexate cu o expresie intre paranteze drepte ([ si ]). Daca expresia este o lista de expresii atunci sirul de indici este un sir ce consta din concatenarea valorilor fiecarei expresii, separate de valoarea variabilei SUBSEP. Aceasta facilitate este utilizata pentru simularea sirurilor cu mai multe dimensiuni. De exemplu:

i = "A" ; j = "B" ; k = "C"

x[i, j, k] = "hello, world\n"

atribuie sirul dintre ghilimele elementului din sirul x, indexat de sirul "A\034B\034C". Operatorul special in poate fi utilizat in instructiuni de control if sau while pentru a decide daca un sir permite un indice de o anumita valoare.

if (val in array)

print array[val]

Acesta poate fi, de asemenea, folosit in bucle for pentru a parcurge toate elementele sirului.

Un element poate fi sters dintr-un sir folosind comanda delete.

Pentru ca o variabila sa fie tratata ca numar se aduna 0 la ea, iar pentru a fi tratata ca sir se concateneaza cu sirul null.

Pentru conversia unui sir la numar se foloseste functia atof. Un numar este convertit la sir folosind valoarea constantei CONVFMT ca sir de formatare pentru sprintf.

2.2.5. Sabloane de selectie si actiuni

2.2.5.1. Sabloane de selectie

AWK este un limbaj orientat pe linie. Pentru fiecare înregistrare din intrare se executa in ordine toate comenzile din programul AWK. Sablonul de selectie este primul si apoi actiunea. Ambele pot lipsi, dar nu deodata. Daca sablonul de selectie lipseste, actiunea este executata pentru fiecare înregistrare, independent de continutul ei. Daca lipseste actiune vor fi afisate toate inregistrarile care satisfac sablonul de selectie. De exemplu, se considera fisierul divizia cu urmatorul continut:

$cat divizia

Munchen Sportul 3 : 2 34000 Spectatori

Leverkusen Steaua 2 : 1 28000 Spectatori

HSV Dinamo 2 : 2 29000 Spectatori

Stuttgart U.Cluj 0 : 1 25000 Spectatori

Bremen Politehnica 2 : 1 30000 Spectatori

Frankfurt Dortmund 0 : 0 27000 Spectatori

O selectie fara actiune ar putea fi:

$awk '$4 > 2' divizia

Munchen Sportul 3 : 2 34000 Spectatori

sau o actiune fara selectie ar fi:

$awk '{ print $1, "a inscris acasa " $4" goluri"}' divizia

Munchen a inscris acasa 3 goluri

Leverkusen a inscris acasa 2 goluri

HSV a inscris acasa 2 goluri

Stuttgart a inscris acasa 0 goluri

Bremen a inscris acasa 2 goluri

Frankfurt a inscris acasa 0 goluri

O selectie cu actiune:

$awk '$4 == $6 { print $1, "", $3, $4 ":" $6 }' divizia

HSV Dinamo 2:2

Frankfurt Dortmund 0:0

O linie de comentariu incepe cu caracterul '#". Liniile vide pot separa instructiuni. O instructiune, in mod normal, se termina cu '\n', in afara cazurilor când linia este terminata cu , { ? : && si ||. O linie poate fi continuata pe urmatoarea daca este terminata cu caracterul '\'.

Pe o linie pot exista mai multe instructiuni daca acestea sunt separate prin caracterul ';'.

Un sablon de selectie AWK pot fi o constructie:

BEGIN

END

/expresie regulata/

expresie relationala

sablon && sablon

sablon || sablon

sablon ? sablon : sablon

(sablon)

! sablon

sablon1, sablon2

BEGIN si END sunt sabloane speciale care nu sunt aplicate pe intrare. Actiunile atasate mai multor sabloane BEGIN sau END sunt concatenate, ca si cum ele ar fi scrise intr-un singur bloc. Actiunile atasate unui sablon BEGIN sunt executate inainte de a citi o intrare, iar cele atasate unui sablon END la terminarea intrarii. Prima se utilizeaza des pentru initializarea variabilelor, definirea separatorilor, iar ultima la afisarea finala a rezultatelor pe ecran. Sabloanele BEGIN si END nu pot fi combinate cu alte sabloane in expresii si trebuie sa aiba atasate actiuni.

Actiunile atasate sabloanelor ce contin expresii regulate sunt executate pentru fiecare linie care se potriveste cu expresia regulata.

O expresie relationala poate folosi orice operatori C. AWK recunoaste operatorii limbajului C:

- operatori de atribuire: =, +=, -=, *=, /= %=;

- operatori aritmetici: +, -, *, /, %, ++, --;

- operatori relationali: <, <=, ==, !=, >=, >;

- operatori logici: !, ||, &&.

In operatiile de cãutare se folosesc des operatorii: ~ si !~. Primul semnifica coincidenta, iar al negarea sa. De exemplu:

$3~/^Da/ # selecteaza campul trei care incepe cu sirul "Da"

Expresia sablon1, sablon2 este un sablon ce permite o selectie ce incepe cu linie selectata de sablon1 si continua pana la linia selectata de sablon2, inclusiv.

2.2.5.2. Actiuni

Instructiunile ce stabilesc actiunile sunt incluse intre acolade. Ele constau din instructiuni uzuale de atribuire, de test si de ciclare existente in majoritatea limbajelor. Operatorii, instructiunile de control si cele de I/E sunt asemanatoare cu cele din C. Instructiunile de control sunt:

if (conditie) instructiune [ else instructiune ]

while (conditie) instructiune

do instructiune while (conditie)

for (expr1; expr2; expr3) instructiune

for (var in array) instructiune

break

continue

delete array[index]

exit [ expresie ]

{ instructiuni }

Exemple:

# if.awk

BEGIN { print "Pentru LoTo rezultatele sunt:"}

{ if ( $4 > $6 ) printf( "\t1")

else if ( $4 == $6 )
printf("\t0")
else printf("\t2")

}

END { printf("\n") }

$awk f if.awk divizia

Pentru LoTo rezultatele sunt:

1 1 0 2 1 0

# lotto.awk

BEGIN { srand() }

{ if ( $1>=$2) {

printf(" %d din %d \n", $2, $1)
for ( i in nrlotto)
delete nrlotto[i]
nr=0
while ( ++z<=$2) {
do {
numar=int( rand()*$1) + 1

} while ( numar in nrlotto)

nrlotto[numar]=numar

}

for ( i=1; i<=$1; i++)

if ( i in nrlotto)
printf("%5d", i)
printf("\n")

}

}

$cat loto.txt

49 6

$awk f lotto.awk loto.txt

6 din 49

2 8 26 31 32 49

Instructiuni de I/E sunt:

close(file) Inchide fisier ( pipe).

getline Seteaza $0 la urmatoarea înregistrare din intrare. Seteaza NF, NR, FNR.

getline var Seteaza var la urmatoarea înregistrare din intare. Seteaza NF, FNR.

next Termina procesarea inregistrarii curente.

print Afiseaza înregistrarea curenta.

print lexpr Afiseaza lista de expresii.

printf fmt, lexpr Formateaza si afiseaza.

system( cmdline) Executa comanda si intoarce starea de exit.

Este permisa redirectarea simpla si cu adaugare a operatiilor de I/E cu fisiere.

Pentru pipe se poate folosi simbolul '|' ( este permisa linia cda | getline). Comanda getline va returna 0 la terminarea fisierului si (-1) in caz de eroare.

Se permite folosirea functiilor printf si sprintf.

2.2.6. Functii predefinite

2.2.6.1. Functii numerice

atan2( y, x) arctg(y/x) (in radiani).

cos(x) cos(x).

exp(x) exponential.

int(x) trunchiaza la intreg.

log(x) logaritm natural.

rand() numar aleator din intervalul [0,1].

sin(x) sin(x).

sqrt(x) radical.

srand(x) numar aleator in [0,x]. Daca x lipseste se foloseste timpul curent.

2.2.6.2. Functii pe siruri

gsub(r, s, t) Substituie global orice subsir, identificat de expresia regulata r, din t cu sirul s si returneaza numãrul de substitutii. Daca t lipseste subsitutia se aplica pe $0.

Exemplu:

gsub(/rot/,"read")

gsub(/a/,"&l&,"canada")

index( s, t) Returneaza indexul sirului t in sirul s, 0 daca t nu este subsir a lui s.

Exemplu: print index("Rokkoko","ko")

length( s) Returneaza lungimea sirului s sau lungimea lui $0, daca s lipseste.

Exemplu: print length("Hallo")

match( s, r) Returneaza pozitia din s in care apare expresia regulata s sau 0 daca r nu este prezenta. Pozitioneaza constantele RSTART and RLENGTH.

Exemplu:

BEGIN { name="schoschonen"

x=match( name, /scho[n]*/)

print x, RSTART, RLENGTH, substr( name, RSTART, RLENGTH)

}

$awk -f f.awk

1 1 4 scho

split(s, a, r) Imparte sirul s functie de separatorul r si distribuie campurile in sirul a. Daca r lipseste se foloseste separatorul FS.

Exemplu:

BEGIN {

strl=split("28.MAI.1994 Ora12:34", data,"[ .:]")

print "Lungimea sirului:", strl

print "data[1]=" data[1]

print "data[2]=" data[2]

print "data[3]=" data[3]

print "data[4]=" data[4]

print "data[5]=" data[5]

}

$awk -f data.awk

Lungimea sirului: 5

data[1]=28

data[2]=MAI

data[3]=1994

data[4]=Ora12

data[5]=34

sprintf(fmt,l) Afiseaza sirul din lista l conform formatului fmt.

sub(r, s, t) Analog gsub, dar substituie prima aparitie.

substr( s,i,n) Returneaza sirul de n caractere ce incepe la pozitia i in sirul s. Daca n este omis se returneaza restul caracterelor.

tolower(s) Converteste caracterele sirului s la litere mici.

toupper(s) Converteste caracterele sirului s la litere mari.

Exemplu:

# implementarea comenzii Unix wc printr-un program awk

{ nc = nc + length($0) + 1

nw = nw + NF

}

END { print NR, "Rinduri", nw, "Cuvinte", nc, "Caractere"}

#awk f func.awk divizia

6 Rinduri 48 Cuvinte 258 Caractere

2.2.7. Functii utilizator

Un program AWK poate contine pe linga secventa de perechi sablon-actiune, optional, definitii de functii utilizator. O functie utilizator poate fi definita intr-un program AWK oriunde e permisa o pereche sablon-actiune. Definitia unei functii trebuie prefixata de cuvantul cheie function sau func.

function nume_functie( lista_de_param) { instructiuni }

Apelul se face prin numele functiei. Parametrii actuali din apelul functiei substituie prin valoare parametrii formali declarati ( Call-by-value). Variabilele locale unei functii sunt declarate ca parametri suplimentari in lista_de_param. Conventia este separarea variabilelor locale de parametrii reali prin spatii suplimentare. De exemplu:

function f(p, q, a, b) { # a, b sunt variabile locale

..... }

/abc/ { ... ; f(1, 2) ; ... }

De exemplu, pentru a extrage luna dintr-o data calendaristica se poate folosi functia luna:

BEGIN {

data1="20.7.80"; luna1=luna( data1)

print luna1 " (" data1 ")"

luna2=luna("20.August.1989")

print luna2

}

func luna( d) {

pct=index( d, ".")

d=substr( d, pct+1)

pct=index( d, ".")

return substr( d, 1, pct1)

}

$awk f luna.awk

7 (20.7.80)

August

Functiile se pot apela recursiv. De exemplu, pentru a inversa fiecare linie dintr-un fisier se poate scrie o functie inv. Programul awk este:

$cat inv.awk

{ printf("|"); inv( $0 "\n"); printf("|\n"); }

function inv( str) {

if ( substr( str, 1, 1) != "\n") {

printf("%s", substr( str, 1, 1))
inv( substr( str, 2))
printf("%s", substr( str, 1, 1))

} else

printf("|<>|")

}

$cat fis

Otto joaca lotto

$awk -f inv.awk fis

|Otto joaca lotto|<--->|ottol acaoj ottO|

3. Aplicatii

3.1. Sa se scrie un program awk care sa afiseze pentru un utilizator numele sau complet, directorul propriu, identificatorul utilizator si de grup.

# finger.awk

BEGIN { FS=":"

name=ARGV[1]

ARGV[1]="/etc/passwd"

}

$5~name {

printf("\n%s >login: %s\n", $5, $1)

printf(" (home directory= %s; user id=%d; group id=%d)\n",

$6, $3, $4);

}

$awk -f finger.awk adi

adi kacso >login: adi

(home directory= /home/adi; user id=504; group id=100)

3.2. Se considera existenta unui fisier conf cu numele tuturor conferintelor din anul in curs. Pentru fiecare conferinta se mentioneaza orasul si tara unde are loc conferinta. Sa se scrie un fisier de comenzi care sa permita selectia conferintelor dintr-o tara.

echo n "Numele fisierului rezultat: "

direct=`pwd`

read fis || break

rep=0

while test $rep = 0

do

echo n "Tara: FR IT GB RO: "

read tara || break

ref=${direct}/conf

fout=${fis}_conf

echo "Fisierul rezultat = $fout "

grep "$tara" $ref > $fout

echo n "O alta selectie [0/1=exit] ? "

read rep || break

done

echo "OK fisierul a fost creat."

3.3. Sa se scrie un program awk care, folosind filtrul find si alte comenzi Unix, calculeaza numãrul de linii din fiecare fisier C intalnit in directorul ( sau directoarele) de cãutare primit ca argument in linia de comanda.

#clc

dire=${@:`pwd`}

find $dire name "*.c" exec wc l {} \; |

awk ' { total += $1; printf("%40s : %7d\n", $2, $1) }

END { printf("\n")

printf("%40s : %7d\n", "Total", total) } '

$clc $HOME

/home/adi/TCPtecho2.c : 51

/home/adi/m/TCPecho.c : 71

...

/home/adi/lib/connectsock.c : 77

/home/adi/TCPtecho.c : 135

/home/adi/TCPtecho1.c : 78

Total : 454

3.4. Sa se scrie un program awk, care primind ca intrare un fisier cu numere asezate sub forma unui tabel, acesta sa efectueze suma elementelor de pe fiecare coloana.

{ for (i=1; i<=NF; i++) 
sum[i] += $i 
if ( NF > max_col) 
max_col = NF 
print "\t" $0 
} 
END { 
sum_txt="Suma:" 
for ( i=1; i<=max_col; i++) 
sum_txt = sum_txt "\t" sum[i] 
print 
print sum_txt 
} 

$awk f sum.awk calcul

12 47 25 
150 23 
10 20 12 15 
30 
Suma: 202 90 37 15 

3.5. Sa se scrie un program awk care primind ca intrare rezultatul comenzii Unix ps sa afiseze un arbore cu procesele din sistem ( optiunile folosite la comanda ps sunt cele existente in Linux).

ps lexw | awk ' 
BEGIN { FS = "[ \t]+" 
slash[0]="|" ; rad=0 
count[0]=0 " *sched( root=0, ?)" 
} 
NR==1 { cmd_pos=index( $0, "COMMAND") 
tty_pos=index( $0, "TTY") 
} 
NR!=1 { s = ++nr_fiu[$5] 
fiu[ $5, s] = $4 
if ( $4 == 0) rad=$4 
else if ( $5==0) 
mark[++x]=$4 
count[$4]=$4 " *" substr( $0, cmd_pos, 30) 
count[$4]=count[$4] " (" $3", "substr($0,tty_pos,5) ")" 
} 
END { t=0; print count[ 0] 
for ( i in mark) 
prel( mark[i]) 
} 
function prel( i, r, j) { 
for ( r=0; r<t; r++) 
printf(" %s", slash[r]) 
printf(" |\n") 
for ( r=0; r<t; r++) 
printf(" %s", slash[r]) 
printf(" +%s\n", count[i]) 
t++ 
for ( j=1; j<=nr_fiu[i]; j++) { 
slash[ t]= (j < nr_fiu[i]) ? "|" : " " 
prel( fiu[i,j]); 
} 
t 
}' 

$pstree

0 *sched( root=0, ?) 
| 
+1 *init (0, ? ) 
| | 
| +6 *bdflush (daemon) (0, ? ) 
| | 
| +7 *update (bdflush) (0, ? ) 
| | 
| +40 */usr/sbin/syslogd (0, ? ) 
| | 
| +42 */usr/sbin/klogd (0, ? ) 
| | 
| +44 */usr/sbin/inetd (0, ? ) 
| | 
| +46 */usr/sbin/lpd (0, ? ) 
| | 
| +49 */usr/sbin/crond (0, ? ) 
| | 
| +53 *selection t ms (0, ? ) 
| | 
| +54 *bash (0, v01 ) 
| | | 
| | +183 *bash (0, v01 ) 
| | | 
| | +184 *ps lexw (0, v01 ) 
| | | 
| | +185 *awk BEGIN { FS = "[ \t]+" (0, v01 ) 
| | 
| +55 *bash (504, v02 ) 
| | 
| +56 *bash (501, v03 ) 
| | | 
| | +160 *joe test.c (501, v03 ) 
| | 
. . . 
| +59 */sbin/agetty 38400 tty6 (0, v06 ) 

4. Probleme propuse

4.1. Ce afiseaza liniile de program awk:

a) n = 5; print $n

b) $cat f1

aaa bbb ccc# ddd# eee fff# ggg

ttt# ggg eee# ccc ddd sss# yyy

$cat exsplit.awk

{ 
i = split($0, Art,"#"); 
for( j=1; j<=i; j++) 
print("Art["j"] = ", Art[j]); 
} 

$awk -f exsplit.awk f1

c) $awk $6 > $4 { print $3, "a cistigat la " $1} divizia

d) $awk '{ printf("%20s: %6d Spectatori, %2d goluri\n", $1, $7, $4+$6) }' divizia

e) $grep '[Uu]nix' ch?/*

4.2. Se considera:

$cat f2

sss aaa ina dan 1

ada sss ina dan 2

ada adi sss dan 3

ada adi ina sss 4

ttt adi ina dan 5

ada ttt ina dan 6

a) Ce afiseaza linia ?

$awk '$3~/sss/, $2~/ttt/ { print ($0); }' f2

b) Ce diferenta exista intre rezultatele programelor awk ?

$cat f3.awk

$3 ~/sss/, $2 ~/ttt/ { print($0); }

$1 ~/sss/, NR=5 { print($0,"*"); }

$cat f4.awk

$3 ~/sss/, $2 ~/ttt/ { print($0); next; }

$1 ~/sss/, NR=5 { print($0,"*"); next; }

4.3. Sa se scrie un program awk care sa permita afisarea rezultatelor din fisierul divizia sub forma:

Oaspeti Gazde | Rezultat

+

Munchen Sportul | 3 : 2 ...

4.4. Sa se scrie un program awk care sa permita conversia unui numar inrteg, primit ca argument in linia de comanda in hexazecimal si octal.

4.5. Sa se scrie un fisier de comenzi care afiseaza un tabel cu toate numele de login din sistem împreuna cu identificatorul utilizator atasat.

4.6. Se da un fisier de intrare care contine articole sub forma:

<nume student># nota1# [nota2#] [nota3] <NL> <nume student>...

Parantezele drepte marcheaza optionalitatea. Se cere sa se scrie un program awk care afiseaza un tabel cu antetul:

Nume student Nota1 Nota2 Nota3 Media

In tabel se vor gasi studentii, ordonati alfabetic care au toate notele si pentru care a fost calculata media. Studentii ramasi vor putea fi afisati la cerere.

Sa se scrie un filtru care sa afiseze numele acelor studenti care au media > 8 si primele doua note minim 8.

4.7. Un fisier de intare are structura:

Nume Prenume Tesa|Muncitor Salariu

Sa se scrie un program awk care determina varsta si salariul mediu pe categorii de personal, precum si persoanele cu salariul minim si maxim.

4.8. Sa se afiseze intr-un tabel cu antet numele fisierului, i-node-ul asociat lui si data la care a fost creat fisierul.

4.9. Sa se scrie un program AWK care prelucreaza 4 fisiere in

care sunt reprezentate matrici 4x4. Programul obtine matricea care are coloanele formate din diagonalele matricilor de intrare.

4.10. Se considera urmatorul program awk pentru rezolvarea problemei celor opt dame:

BEGIN { 
for ( i=1; i<=8; i++) collib[i] = 1 
for ( i=2; i<=16; i++) ds[i] = 1 
for ( i=7; i<=7; i++) dp[i] = 1 
regina_pe() 
} 

Sa se scrie functia regina_pe, care sa permita obtinerea tuturor solutiilor. Pentru a vizualiza plasarea damelor pe tabla se va scrie o functie afis.

4.11. Sa se scrie un program awk, care primind ca intrare un fisier text cu randuri mai lungi de 40 de caractere il rescrie pe randuri de 30 de caractere.