Як можна підсумовувати числа по рядках у файлі


24

У мене є файл, який виглядає приблизно так:

1
3
4
1
4
3
1
2

Як я можу знайти загальну суму цього (тобто 1 + 3 + 4 + 1 + 4 + 3 + 1 + 2 = 19)?


1
У контексті я підраховую кількість значків, які я маю на Ask Ubuntu від API стека Exchange.
— Тім

Зcat badges.json | grep -o '"award_count":[0-9],"rank":"gold"' | grep -o [0-9]
— Тім

Хоча зараз я розумію, що в API є badge_countметод.
— Тім

Якщо ви рахуєте значки з API, мова, якою ви користуєтесь для запиту API, не може цього зробити (python, javascript)?
— Брайам

Відповіді:


42

bcза допомогою невеликої допомоги, pasteщоб отримати рядки в єдиній з +роздільником:

paste -sd+ file.txt | bc

Щоб використовувати висновок grep(або будь-яку іншу команду) замість статичного файлу, передайте grepSTDOUT 's в STDIN paste:

grep .... | paste -sd+ | bc

Приклад:

% cat file.txt            
1
3
4
1
4
3
1
2

% paste -sd+ file.txt | bc
19

% grep . file.txt | paste -sd+ | bc
19

Якщо потрібно використовувати bash, то ви можете використовувати масив для збереження вмісту файлу, а потім перебирати елементи або ви можете читати файл за рядком і робити суму для кожного рядка, другий підхід був би більш ефективним:

$ time { nums=$(<file.txt); for i in ${nums[@]}; do (( sum+=i )); done; echo $sum ;}
19

real    0m0.002s
user    0m0.000s
sys 0m0.000s

$ time { while read i; do (( sum+=i )); done <file.txt; echo $sum ;}
19

real    0m0.000s
user    0m0.000s
sys 0m0.000s

Хм, приємно. Вибачте, що змінили питання: чи можу я змінити це, щоб прийняти греп-вихід (або зробити його таким, як cat file.txt | bc?
— Тім

@Tim Перевір мої зміни
— heemayl

Та, це було просто!
— Тім

2
Стродий спосіб не працював для мене, поки я не виявив в іншій відповіді, що мені довелося використовувати paste -sd+ -. Будь ласка, виправте це.
— Ксерус

19

Ви можете також використовувати awk. Для підрахунку загальної кількості рядків у файлах * .txt, що містять слово "привіт":

grep -ch 'hello' *.txt | awk '{n += $1}; END{print n}'

Щоб просто підсумувати числа у файлі:

awk '{n += $1}; END{print n}' file.txt

Але якщо цей рядок має значення "4", він не буде рахувати 4, це буде. Він буде рахувати 1.
— Тім

Ні, це буде рахувати 4.
— CrazyApe84

Я хочу загальну кількість у файлі. Це робить це?
— Тім

Я думав, ти змінив своє питання на вихід grep. Я робив певні припущення. Я додам, як просто підсумовувати значення у файлі.
— CrazyApe84

2
Так. Це дійсно та сама відповідь, що і heemayl's, але замість пасти та bc вона використовує awk, що в кінцевому підсумку дає набагато більше гнучкості. Тим не менш, його відповідь хороша, і він був першим, тому він заслуговує на ваш голос!
— CrazyApe84

7

Використовуйте numsumз упаковки num-utils!

(Можливо, вам доведеться sudo apt-get install num-utils)

Команда numsumвиконує лише те, що вам потрібно за замовчуванням;

$ numsum file.txt 
19

Читання тестових чисел по рядках з stdin:

$ printf '
1 
3
4
1
4
3
1
2' | numsum
19

Або читання з одного рядка:

$ printf '1 3 4 1 4 3 1 2' | numsum -r
19


Більше комунальних послуг

Пакет містить деякі інші утиліти для обробки номерів, які заслуговують на те, щоб бути більш відомими:

numaverage   - find the average of the numbers, or the mode or median
numbound     - find minimum of maximum of all lines
numgrep      - to find numbers matching ranges or sets
numinterval  - roughly like the first derivative
numnormalize - normalize numbers to an interval, like 0-1
numrandom    - random numbers from ranges or sets, eg odd.  
numrange     - similar to seq
numround     - round numbers up, down or to nearest

і більш загальну команду калькулятора numprocess,
яка застосовує вираз із командного рядка до чисел у рядках введення.


1

Ви можете використовувати awkнативну програму Linux, яка корисна для сканування та обробки файлів з малюнком на рядок. Що стосується вашого питання, це призведе до того, що ви хочете:

awk 'BEGIN { sum=0 } { sum+=$1 } END {print sum }' file.txt

Труби також приймають:

cat file.txt | awk 'BEGIN { sum=0 } { sum+=$1 } END {print sum }'

BEGIN{}Блоку не потрібно , дивіться відповідь CrazyApe84 .
— тердон

Ця проблема є зайвою, але я вважаю за краще включити її через дидактичну мету.
— гвара

Але чого це вчить? Це зайве для кожної проблеми, awkце не C, вам не потрібно встановлювати змінну перед її використанням. Спробуйте awk 'BEGIN{print c+=1}'.
— тердон

BEGIN {}Блок не був розроблений просто для ініціалізації змінних. Він бере участь у специфікації дизайну. Отже, з деяких проблем це може знадобитися.
— гвара

0

Це досить просте використання bashсценаріїв.

SUM=0; for line in `cat file.txt`; do SUM=$((SUM + line)); done

Це набагато простіше і набір інструментів мінімалістичний, ніж поточне рішення.
— Дет

0

Розчин Perl:

$ perl -lnae '$c+=$_;END{print $c}' input.txt                                                                            
19

Вищезазначене може підсумовувати всі числа в кількох файлах:

$ perl -lnae '$c+=$_;END{print $c}' input.txt input2.txt                                                                 
34

Для декількох файлів, поданих у командному рядку, де ми хочемо побачити суму чисел в окремому файлі, ми можемо це зробити:

$ perl -lnae '$c+=$_;if(eof){printf("%d %s\n",$c,$ARGV);$c=0}' input.txt input2.txt                                      
19 input.txt
15 input2.txt


0

Простий підхід полягає у використанні вбудованої функції вашої оболонки:

SUM=0; while read N; do SUM=$((SUM+N)); done </path/to/file
echo $SUM

Це читає ваш файл лінійно, підбиває підсумки та друкує результат.

Якщо ви хочете використовувати трубу і використовувати лише 1-й ряд, це працює так:

SUM=0
your_command | while read -r LINE; do for N in $LINE; do break; done; SUM=$((SUM+N)); done
echo $SUM

Отримання першого елемента робиться так:

LIST="foo bar baz"
for OBJ in $LIST; do break; done
echo $OBJ

foo
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.