bash tricks: compararea a doua valori zecimale
Tema: sa se scrie un script bash care compara load average cu o valoare data. Se dau puncte suplimentare pentru portabilitate si flexibilitate.
Ha, intrebare de grupa mica! Simplu: preiei valoarea din /proc, cu cut -f2 -d\ /proc/loadavg si o compari cu valoarea citita din fisierul de configurare.
Aha. Cum compari 0.75 cu 1.5 ?
- cu test nu merge, nu suporta decat operatii cu intregi;
- cu arithmetic evaluation din bash iarasi nu merge, din acelasi motiv;
- expr are aceeasi problema;
- bc nu e neaparat disponibil out of the box;
- un trick foarte perfid ar fi fost sa ma bazez pe faptul ca in /proc/loadavg apar exact 2 zecimale, asa ca puteam scoate punctul cu tr si aveam garantia ca am inmultit cu 100, asta ar fi insemnat un efort semnificativ de a garanta formatul in care apare valoarea data de utilizator, contrazicand principiul minimei surprize (diferente esentiale intre 2, 2.0, 2.00);
- sa pornesc perl dintr-un script bash doar ca sa compar 2 numere e de-a dreptul hilar.
Cea mai decenta solutie gasita a fost cu awk: if [ $(echo $loadavg $test | awk '{if ($1>$2) print 1}') ] ; then ...
Sper sa mai fie de folos cuiva (sau macar sa aflu o solutie mai buna).
PS: wordpressul insista foarte tare sa schimbe apostroafele cu backtickuri sau alte chestii similare, asa ca grija mare la copy-paste!
5 Responses to “bash tricks: compararea a doua valori zecimale”
October 13th, 2006 at 8:26 am
printf se incadreaza la portabilitate? Ca daca da, atunci un printf cu format (de ex.) %010.4 ar cam aduce 2, 2.0, 2.00 la aceasi forma 0002.0000
October 13th, 2006 at 8:40 am
hmm, uite ca nu m-am gandit.
if [ `printf '%010.4f' $loadavg| tr -d .` gt `printf '%010.4f' $test| tr -d .` ] ; then …
Nice, dar cred in continuare ca e mai simplu cu awk
October 13th, 2006 at 3:06 pm
“sa pornesc perl dintr-un script bash doar ca sa compar 2 numere e de-a dreptul hilar.”
Nah, hilar e ca tu te sperii de parca ar trebui sa pornesti Java.
]$ time perl -ane’$F[0]>shift&&print 1′ /proc/loadavg 0.01
real 0m0.006s
user 0m0.001s
sys 0m0.004s
]$ time awk -v v=0.01 ‘{if ($1>v) print 1}’ /proc/loadavg
real 0m0.005s
user 0m0.000s
sys 0m0.004s
October 13th, 2006 at 6:54 pm
Well, voiam sa zic ca mai bine rescriam tot scriptul in perl, nu ma asteptam sa ma lovesc de o problema atat de marunta si ca o forma sau alta de awk gasesti garantat pe orice masina linux.
Si ca exista 3 awk-uri in Debian, tu pe care il ai?
October 13th, 2006 at 7:26 pm
“o forma sau alta de awk gasesti garantat pe orice masina linux.”
Ofc, just like Perl.
“Si ca exista 3 awk-uri in Debian, tu pe care il ai?
”
GNU. Always GNU. Just GNU.
ps: NU e flama perl vs awk, inutila de altfel (pt mine) – stii ce prefer – doar exprimarea cu “pornitu” perlului din bash a fost exagerata, dupa cum arata si cifrele. E ca si cum ai “porni” awk.
pps: Nu tra sa rescrii totul in Perl (limbaj), dar poti folosi perl (program) si ca scula de sistem, inlocuitor sed/awk/cat/tail/sh/etc cu mare sugces. E una din puterile lui subversive la adresa Unix.