- Сложить массив чисел на bash, vic, 15:25 , 27-Фев-09 (1)
>Есть файл вида > >$cat total.bytes >1962647280 >154580283 >85368270 >256233601 >2448176455 >3211021168 >392011779 в минус уходит из-за переполнения int. попробуйте так: sum = 0; cat total.bytes | while read num ; do sum=`echo $sum+$num" | bc -q` ; done ; echo $sum
- Сложить массив чисел на bash, vic, 15:45 , 27-Фев-09 (2)
а еще лучше так result=`sum=0 ; (while read num; do sum=$(echo "$sum+$num" | bc -q); done ; echo $sum) < total.bytes` echo $result
- без цикла, Andrey Mitrofanov, 17:01 , 27-Фев-09 (10)
$ cat total.bytes 1962647280 154580283 85368270 2562336012448176455 3211021168 392011779 $ ( tr "\n" "+" <total.bytes |sed 's!+\+!+!g;s!^+\|+$!!g'; echo ) |bc 8510038836 $ tr "\n" "+" <total.bytes |sed 's!+\+!+!g;s!^+\|+$!!g'|xargs|bc 8510038836 $ egrep -o '[0-9]+' <total.bytes |tr "\n" "+" |sed 's!+$!\n!'|bc 8510038836 $ _
- без цикла, Stone, 17:13 , 27-Фев-09 (13)
>[оверквотинг удален] >392011779 > > >$ ( tr "\n" "+" <total.bytes |sed 's!+\+!+!g;s!^+\|+$!!g'; echo ) |bc >8510038836 >$ tr "\n" "+" <total.bytes |sed 's!+\+!+!g;s!^+\|+$!!g'|xargs|bc >8510038836 >$ egrep -o '[0-9]+' <total.bytes |tr "\n" "+" |sed 's!+$!\n!'|bc >8510038836 >$ _ То ли я что-то не то делаю, но у меня на все это syntax error выдает
- без цикла, vic, 17:14 , 27-Фев-09 (14)
>[оверквотинг удален] >392011779 > > >$ ( tr "\n" "+" <total.bytes |sed 's!+\+!+!g;s!^+\|+$!!g'; echo ) |bc >8510038836 >$ tr "\n" "+" <total.bytes |sed 's!+\+!+!g;s!^+\|+$!!g'|xargs|bc >8510038836 >$ egrep -o '[0-9]+' <total.bytes |tr "\n" "+" |sed 's!+$!\n!'|bc >8510038836 >$ _ как бы bc не отвалился, хз сколько там чисел echo `cat total.bytes` | tr " " "+" | bc это все хорошо, а если там чисел столько что bc отвалится
- без цикла, Stone, 17:20 , 27-Фев-09 (16)
>как бы bc не отвалился, хз сколько там чисел >echo `cat total.bytes` | tr " " "+" | bc >это все хорошо, а если там чисел столько что bc отвалится Во, самый короткий вариант, и работает в баше и в sh!!!
- без цикла, vic, 17:21 , 27-Фев-09 (17)
>[оверквотинг удален] >>8510038836 >>$ tr "\n" "+" <total.bytes |sed 's!+\+!+!g;s!^+\|+$!!g'|xargs|bc >>8510038836 >>$ egrep -o '[0-9]+' <total.bytes |tr "\n" "+" |sed 's!+$!\n!'|bc >>8510038836 >>$ _ > >как бы bc не отвалился, хз сколько там чисел >echo `cat total.bytes` | tr " " "+" | bc >это все хорошо, а если там чисел столько что bc отвалится какая настойчивая мысль....)))))))))
- с бенчмарками :), Andrey Mitrofanov, 19:56 , 02-Мрт-09 (18)
>>$ ( tr "\n" "+" <total.bytes |sed 's!+\+!+!g;s!^+\|+$!!g'; echo ) |bc >>$ tr "\n" "+" <total.bytes |sed 's!+\+!+!g;s!^+\|+$!!g'|xargs|bc >>$ egrep -o '[0-9]+' <total.bytes |tr "\n" "+" |sed 's!+$!\n!'|bc >как бы bc не отвалился, хз сколько там чисел Действительно! %) >echo `cat total.bytes` | tr " " "+" | bc >это все хорошо, а если там чисел столько что bc отвалится $ cat ./x41 #!/bin/bash n=10 for((i=1;i<7;i++)); do yes | head -$n |sed 's!y!1000000001!' | (\ /usr/bin/time bc <(echo 'sum=0;while((val=read())!=0){sum+=val}; sum') |\ tr -d "\n"|wc -c ) 2>&1 |tr "\n" " "|awk '{print '"$((${#n}-1))"'" "$NF" "$1" "$3" "$4;exit}' n="${n}0" done # #done$ ./x41 1 11 0.00user 0:00.00elapsed 0%CPU 2 12 0.00user 0:00.00elapsed 44%CPU 3 13 0.01user 0:00.01elapsed 70%CPU 4 14 0.09user 0:00.10elapsed 85%CPU 5 15 0.88user 0:01.06elapsed 83%CPU 6 16 8.82user 0:10.20elapsed 86%CPU $ _
Вот такой вариант, соответственно, не подавился суммированием миллиона (десяти лениво было ждать) чисел: bc <(echo 'sum=0;while((val=read())!=0){sum+=val}; sum') Из трёх моих первых до таких "высот" не дожил ни один: xargs умер раньше всех, а при передаче сотни тысяч(или типа того) слагаемых в виде строки 1+1+1+,,, bc слишком активно кушал память (типа, всю свободную и начинал "свопиться" = тормозить себя и всю систему). PS: <(echo '...') - башизм, чтоб сэкономить "лишний" файл. PPS: Первая колонка "бенчмарка" - log($числа_слагаемых), вторая - "длинна" суммы.
- и, кстати, 'больше' не работает :/, Andrey Mitrofanov, 18:22 , 28-Май-09 (24)
>bc <(echo 'sum=0;while((val=read())!=0){sum+=val}; sum') Обновился с Debian 4.0 "Etch" на Debian 5.0 "Lenny" (bc 1.06-20 -> 1.06.94-3, bash 3.1dfsg-8 -> 3.2-4 и проч.) и это заклинание больше не работает. "=read())!=0" в нём костыль, конечно, по сравнению с "while read val; do" в bash-е: конец файла от числа 0 не отличает. А в Lenny и вообще не работает...
- Сложить массив чисел на bash, Stone, 15:47 , 27-Фев-09 (3)
>[оверквотинг удален] >>256233601 >>2448176455 >>3211021168 >>392011779 > >в минус уходит из-за переполнения int. > >попробуйте так: >sum = 0; cat total.bytes | while read num ; do sum=`echo >$sum+$num" | bc -q` ; done ; echo $sum Тоже подумал что от переполнения, но когда сложил вручную несколько первых чисел, но все нормально Ваш скрипт к сожалению не работает, там вроде кавычки забыли, я поставил, все равно не пашет
- Сложить массив чисел на bash, Stone, 15:51 , 27-Фев-09 (4)
>[оверквотинг удален] >> >>попробуйте так: >>sum = 0; cat total.bytes | while read num ; do sum=`echo >>$sum+$num" | bc -q` ; done ; echo $sum > >Тоже подумал что от переполнения, но когда сложил вручную несколько первых чисел, >но все нормально > >Ваш скрипт к сожалению не работает, там вроде кавычки забыли, я поставил, >все равно не пашет А вот второй скрипт пашет, спасибо!
- Сложить массив чисел на bash, allez, 15:56 , 27-Фев-09 (5)
>#!/bin/sh >cat total.bytes | \ >while read line; >do >let y=y+line; >done >echo $y Обратите особое внимание на строку с "let", она у вас не может работать.
$ cat total.bytes 1962647280 154580283 85368270 256233601 2448176455 3211021168 392011779$ cat script.sh #!/bin/sh while read line; do let y=$y+$line; done < total.bytes echo $y $ ./script.sh 8510038836
- Сложить массив чисел на bash, Stone, 16:11 , 27-Фев-09 (6)
>[оверквотинг удален] >while read line; >do > let y=$y+$line; >done < total.bytes >echo $y > >$ ./script.sh >8510038836 > > Так тоже минусы выводит у меня!
- Сложить массив чисел на bash, vic, 16:39 , 27-Фев-09 (7)
>[оверквотинг удален] >> let y=$y+$line; >>done < total.bytes >>echo $y >> >>$ ./script.sh >>8510038836 >> >> > >Так тоже минусы выводит у меня! А вы cat | while делаете или while .. done < file ? В первом случае может неявно вызываться субшелл и как следствие переменная y может быть не видна т.к ее область видимости - субшелл, отсюда глюки. Что за система? (uname -a && sh --version) ?
- Сложить массив чисел на bash, Stone, 16:46 , 27-Фев-09 (8)
>А вы cat | while делаете или while .. done < file >? >В первом случае может неявно вызываться субшелл и как следствие переменная y >может быть не видна т.к ее область видимости - субшелл, отсюда >глюки. > >Что за система? (uname -a && sh --version) ? $ cat xyz.sh #!/bin/sh while read line; do let m=$m+$line; done < total.bytes.back echo $m $ ./xyz.sh 1962647280 2117227563 -2092371463 -1836137862 311345785 -1836137864 -1444126085 -1444126085 $ uname -a FreeBSD 7.0-RELEASE FreeBSD 7.0-RELEASE #0: Fri Apr 11 20:30:15 MSD 2008 $ sh --version Illegal option --
- Сложить массив чисел на bash, Stone, 16:47 , 27-Фев-09 (9)
О, а если bash поставить, то работает!Дело в sh значит$ cat xyz.sh #!/usr/local/bin/bash while read line; do let m=$m+$line; done < total.bytes.back echo $m $ ./xyz.sh 8510038836
- Сложить массив чисел на bash, vic, 17:04 , 27-Фев-09 (11)
>О, а если bash поставить, то работает!Дело в sh значит однако суровый sh в freebsd :)) result=`y=0; (while read line; do let y=$y+$line; done ; echo $y) < total.bytes` echo $result что буит?
- Сложить массив чисел на bash, Stone, 17:09 , 27-Фев-09 (12)
>>О, а если bash поставить, то работает!Дело в sh значит > >однако суровый sh в freebsd :)) > >result=`y=0; (while read line; do let y=$y+$line; done ; echo $y) < >total.bytes` >echo $result > >что буит? $ ./xyz.sh 1962647280 2117227563 -2092371463 -1836137862 311345785 -1836137864 -1444126085 -710494993 1436988654 -1190184973 957298674 -1190184975 338450189 623557529 790395966 924888457 -1222595192 138906228 1676938475 1857929764 1857956963 -765632036 1316748116 -1132369225 1015114422 1520280995 1520280995 Тож самое, минусы.А как узнать версию sh?и его вообще можно обновить, в портах нету его
- Сложить массив чисел на bash, vic, 17:19 , 27-Фев-09 (15)
>Тож самое, минусы.А как узнать версию sh?и его вообще можно обновить, в >портах нету его уже можно не парится, итак видно что суровый :) а минусы это переполнение (ибо сурово), поэтому во втором варианте я и предложил bc :)
- Сложить массив чисел на bash, 0dmin, 23:00 , 03-Мрт-09 (22)
>>О, а если bash поставить, то работает!Дело в sh значит >однако суровый sh в freebsd :)) Номальный POSIX Shell. PS: А да - во фряхе _внезапно!_ bash зовётся bash'ем а не sh :)
- Сложить массив чисел на bash, andreik, 16:31 , 03-Мрт-09 (19)
awk 'BEGIN {c=0} {c=c+$0} END {printf("%.0f\n", c)}' total.bytes
- Сложить массив чисел на bash, Andrey Mitrofanov, 18:04 , 03-Мрт-09 (20)
>awk 'BEGIN {c=0} {c=c+$0} END {printf("%.0f\n", c)}' total.bytes Если точности плавающих - хватает, то да, так быстрее: $ cat ./x5 #!/bin/bash n=10 for((i=1;i<8;i++)); do yes | head -$n |sed 's!y!18446744073799!' | (\ /usr/bin/time gawk 'BEGIN {c=0} {c=c+$0} END {printf("%.0f\n", c)}' |\ tr -d "\n" #|wc -c ) 2>&1 |tr "\n" " "|awk '{print '"$((${#n}-1))"'" "$NF" "$1" "$3" "$4;exit}' n="${n}0" done $ ./x5 1 184467440737990 0.00user 0:00.00elapsed 0%CPU 2 1844674407379900 0.00user 0:00.00elapsed 0%CPU 3 18446744073799512 0.00user 0:00.00elapsed 0%CPU 4 184467440737950784 0.00user 0:00.02elapsed 60%CPU 5 1844674407378830848 0.10user 0:00.22elapsed 47%CPU 6 18446744074118029312 0.94user 0:02.66elapsed 36%CPU 7 184467440723846004736 9.78user 0:24.68elapsed 40%CPU # _ То же самое с s/gawk/mawk/:
$ ./x5 1 184467440737990 0.00user 0:00.00elapsed 0%CPU 2 1844674407379900 0.00user 0:00.00elapsed 133%CPU 3 18446744073799512 0.00user 0:00.00elapsed 0%CPU 4 184467440737950784 0.00user 0:00.01elapsed 26%CPU 5 1844674407378830848 0.06user 0:00.17elapsed 38%CPU 6 18446744074118029312 0.51user 0:01.71elapsed 31%CPU 7 184467440723846004736 5.28user 0:19.83elapsed 27%CPU
- Сложить массив чисел на bash, krigs, 03:31 , 25-Май-09 (23)
>[оверквотинг удален] >-1836137862 >311345785 >-1836137864 >-1444126085 >-710494993 >1436988654 >-1190184973 > >Т.е первые два числа сложил, а потом почему-то минусы какие-то появляются >что делаю не так? Только что наткнулся на книгу Евгения Миньковского (http://house.hcn-strela.ru/BSDCert/BSDA-course/index.html) - там и почерпнул идею :) $ cat count #!/bin/sh sum=0 for num in `cat ./total.bytes`; do sum=`echo $sum+$num | bc` done echo $sum $ ./count 8510038836 Просто и эффектно. Кстати этот скрипт также будет обрабатывать числа, даже если они введены в файле через пробелы или табуляцию. А программа bc работает и с числами с десятичной точкой.
- Сложить массив чисел на bash, Andrew, 23:57 , 29-Май-09 (25)
>[оверквотинг удален] >sum=0 >for num in `cat ./total.bytes`; do > sum=`echo $sum+$num | bc` >done >echo $sum >$ ./count >8510038836 >Просто и эффектно. Кстати этот скрипт также будет обрабатывать числа, даже если >они введены в файле через пробелы или табуляцию. А программа bc >работает и с числами с десятичной точкой. Блин.... только хотел написать про bc, оказалось уже в цитате написано. А если по существу, если вы покурите man bc более вдумчиво, решение выйдет еще более элегантное. - Сложить массив чисел на bash, anonymous, 06:01 , 30-Май-09 (26)
>Просто и эффектно.Ни разу не эффективно на каждое сложение запускать новый процесс bc.
- Сложить массив чисел на bash, angra, 08:28 , 31-Май-09 (27)
Использовать bash для этой задачи вообще не эффективно, тем более, что в конечном итоге опять таки используется bc, так почему просто не привести файл в удобный для bc вид. Но если хочется: for s in 1;do for i in `cat text` ;do echo -n "$i"+;done;echo 0;done |bc
- а сертифицированные BSDA читают книги, Andrey Mitrofanov, 17:25 , 01-Июн-09 (28)
>Использовать bash для этой задачи вообще не эффективно, тем более, что в >конечном итоге опять таки используется bc, так почему просто не привести >файл в удобный для bc вид. Но если хочется: >for s in 1;do for i in `cat text` ;do echo -n >"$i"+;done;echo 0;done |bc |*) for не нужен. back-ticks не нужен (больше ~130к файла не влезет). Всё "как положено": awk быстрее, на bc точность не страдает... $ cat ./x6 #!/bin/bash n=10 for((i=1;i<8;i++)); do yes | head -$n |sed 's!y!10000000000001!' | (\ { echo "sum=0"; sed 's/.\+/sum+=\0/'; echo 'print sum," "'; } | /usr/bin/time bc ) 2>&1 |awk '{print '"$((${#n}-1))"'" "$1" "$2" "$4" "$5;exit}' n="${n}0" done $ ./x6 1 100000000000010 0.00user 0:00.00elapsed 0%CPU 2 1000000000000100 0.00user 0:00.00elapsed 200%CPU 3 10000000000001000 0.00user 0:00.00elapsed 100%CPU 4 100000000000010000 0.03user 0:00.05elapsed 61%CPU 5 1000000000000100000 0.36user 0:00.63elapsed 57%CPU 6 10000000000001000000 3.86user 0:06.94elapsed 56%CPU 7 100000000000010000000 39.76user 1:12.61elapsed 55%CPU $ cat ./x6a #!/bin/bash n=10 for((i=1;i<8;i++)); do yes | head -$n |sed 's!y!10000000000001!' | (\ /usr/bin/time mawk 'BEGIN {c=0} {c=c+$0} END {printf("%.0f ", c)}' ) 2>&1 |awk '{print '"$((${#n}-1))"'" "$1" "$2" "$4" "$5;exit}' n="${n}0" done $ ./x6a 1 100000000000010 0.00user 0:00.00elapsed 0%CPU 2 1000000000000100 0.00user 0:00.00elapsed 100%CPU 3 10000000000000900 0.00user 0:00.00elapsed 57%CPU 4 100000000000000912 0.00user 0:00.01elapsed 53%CPU 5 1000000000000001024 0.05user 0:00.15elapsed 38%CPU 6 10000000000000002048 0.48user 0:01.56elapsed 32%CPU 7 99999999978526310400 5.17user 0:15.50elapsed 34%CPU $ _
- а сертифицированные BSDA читают книги, angra, 00:52 , 02-Июн-09 (29)
>|*) for не нужен. back-ticks не нужен (больше ~130к файла не влезет). Андрей, неужели ты думаешь, что я делаю так как написал. Была мысль показать while read с перенаправлением, но ведь объяснять бы пришлось. Задача была показать в простом виде как избавится от множественных вызовов bc(или любой другой программы) в подобных случаях, как следствие внес минимум изменений в код из книжки(про умственную отсталость автора книги отдельный разговор). Мое отношение к башу в такой задаче я в любом случае выразил однозначно.
|