Как я могу сложить числа в строках в файле

24

У меня есть файл, который выглядит так:

1
3
4
1
4
3
1
2

Как я могу найти сумму всего этого (т.е. 1 + 3 + 4 + 1 + 4 + 3 + 1 + 2 = 19)?

Тим
источник
1
Для контекста я считаю количество значков, которые я имею на Ask Ubuntu из API Stack 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 в 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
heemayl
источник
Хм приятно. Извините, что изменил вопрос: могу ли я изменить это, чтобы принять вывод grep (или сделать его одной строкой, как cat file.txt | bc?
Тим
@Tim Проверьте мои правки
Heemayl
Та, это было просто!
Тим
2
путь stdin не работал для меня, пока я не обнаружил в другом ответе, который я должен был использовать paste -sd+ -. Пожалуйста, исправьте это.
Xerus
19

Вы также можете использовать awk. Чтобы подсчитать общее количество строк в файлах * .txt , содержащих слово «привет»:

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

Чтобы просто сложить числа в файле:

awk '{n += $1}; END{print n}' file.txt
CrazyApe84
источник
Но если эта строка имеет значение «4», она не будет считаться 4, не так ли? Это будет считаться 1.
Тим
Нет, это будет считаться 4.
CrazyApe84
Я хочу общее количество чисел в файле. Это делает это?
Тим
Я думал, что вы изменили свой вопрос на вывод grep. Я делал некоторые предположения. Я добавлю, как просто суммировать значения в файле.
CrazyApe84
2
Да. Это действительно тот же ответ, что и у Heemayl, но вместо paste и 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,
которая применяет выражение из командной строки к числам во входных строках.

Volker Siegel
источник
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 }'
gwarah
источник
Там нет необходимости в 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
zomfg_zombie
источник
Это намного проще и набор инструментов минималистичен, чем текущее решение.
Det
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

Просто -

awk '{total+=$1} END{print total}' file

складывает числа и дает вам общее количество.

Суфьян Рамзан
источник
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
Бастиан Битторф
источник