Sumowanie wartości bez pętelek
Posted on Sat 06 November 2004 in Tips text {sed, awk, perl, etc.}
• [2 min read]
Mam polecenie, ktore zwraca takie wartosci:
111
123
124
125
Mysle sobie, zeby to cholerstwo przepuscic przez xargs expr +, zeby mi te wartosci zsumowalo. Petelek wolalbym unikac. Da sie?
Bez petelek? W jaki sposob? Nawet gdyby ta petelka miala skonstruowac wyrazenie, powiedzmy, LISP-u i przekazac do ewaluacji. Chyba, ze to sa zawsze cztery i zawsze te same liczby. No to wtedy "echo 483" jest tym co potrzeba. :-)
Mozna ta petelke "schowac"
'{sum += $1}END{print sum}'
Podejrzewam, ze sztuki takie jak
echo 111 123 124 125 +++p |dc
nie sa satysfakcjonujace. :-) Chociaz
( echo 111; echo 123; echo 124; echo 125; echo +++p ) |dc
da taki sam wynik.
data=$( seq 122 125 )
sum=$(expr $(echo $data | sed 's/ / + /g'))
echo $sum
Tyle, ze petelka jest tez tutaj "schowana" w 'sed ..../g'. 'seq' po to zeby zasymulowac ten proces ktory daje kolumienke liczb. Ale, ale. Rzeczywiscie mozna zrobic ta petle przy pomocy xargs.
data=$(seq 122 125 | xargs -i'x' echo -n "x + " ; echo 0)
expr $data
Bardzo to krucha ta konstrukcja. Co zlego z jawnymi petlami?
Nie warto unikać pętli.
seq 122 125 | perl -e 'while (<>) {$sum += $_} print "$sum\\n"'
No, jak jawne petle sa ok, i sa to liczby calkowite, to perl tez nie jest potrzebne.
$ seq 3000 |(while read r; do s=$((r+s)); done; echo $s)
4501500
Napewno bedzie szybciej niz 'xargs' i 'expr'. :-) Z tym, ze przy odpowiednio duzych sumach moze sie zrobic "overflow" podczas gdy perl czy awk i ten szczegol ukryja. perl czy awk bedzie znaczenie szybsze niz powyzsze - jezeli tych liczb jest dostatecznie duzo zeby sie to dalo mierzyc.
$ time seq 3000 6000 |(while read r; do s=$((r+s)); done; echo $s)
13504500
real 0m0.272s
user 0m0.250s
sys 0m0.010s