Команда оболочки для суммирования целых чисел, по одному на строку? - PullRequest
765 голосов
/ 16 января 2009

Я ищу команду, которая примет в качестве входных данных несколько строк текста, каждая строка содержит одно целое число, и выведет сумму этих целых чисел.

Для справки: у меня есть файл журнала, который включает измерения времени, поэтому с помощью поиска соответствующих строк и небольшого переформатирования sed я могу перечислить все значения времени в этом файле. Тем не менее, я хотел бы вычислить итоговое значение, и у меня не осталось мыслей относительно любой команды, к которой я могу направить этот промежуточный вывод, чтобы получить окончательную сумму. Я всегда использовал expr в прошлом, но если он не работает в режиме RPN, я не думаю, что он справится с этим (и даже тогда это будет сложно).

Чего мне не хватает? Учитывая, что, вероятно, есть несколько способов достичь этого, я буду рад прочитать (и поддержать) любой подход, который работает, даже если кто-то уже опубликовал другое решение, которое выполняет эту работу.

Схожий вопрос: Кратчайшая команда для вычисления суммы столбца вывода в Unix? (кредиты @ Андрей )


Обновление : Вау, как и ожидалось, здесь есть несколько хороших ответов. Похоже, мне определенно придется провести awk более глубокую проверку в качестве инструмента командной строки в целом!

Ответы [ 42 ]

2 голосов
/ 06 марта 2012

Заранее извиняюсь за удобочитаемость обратных галочек ("` "), но они работают в оболочках, отличных от bash, и, следовательно, более удобны для вставки. Если вы используете оболочку, которая принимает его, формат $ (command ...) будет гораздо более читабельным (и, следовательно, отлаживаемым), чем `command ...`, поэтому не стесняйтесь изменять для вашего здравого смысла.

В моем bashrc есть простая функция, которая будет использовать awk для вычисления количества простых математических элементов

calc(){
  awk 'BEGIN{print '"$@"' }'
}

Это будет делать +, -, *, /, ^,%, sqrt, sin, cos, круглые скобки .... (и многое другое в зависимости от вашей версии awk) ... вы можете даже получить фантазию с printf и отформатировать вывод с плавающей точкой, но это все, что мне обычно нужно

для этого конкретного вопроса, я бы просто сделал это для каждой строки:

calc `echo "$@"|tr " " "+"`

поэтому блок кода для суммирования каждой строки будет выглядеть примерно так:

while read LINE || [ "$LINE" ]; do
  calc `echo "$LINE"|tr " " "+"` #you may want to filter out some lines with a case statement here
done

Это если вы хотите суммировать их только построчно. Однако в общей сложности каждое число в файле данных

VARS=`<datafile`
calc `echo ${VARS// /+}`

Кстати, если мне нужно что-то сделать быстро на рабочем столе, я использую это:

xcalc() { 
  A=`calc "$@"`
  A=`Xdialog --stdout --inputbox "Simple calculator" 0 0 $A`
  [ $A ] && xcalc $A
}
2 голосов
/ 26 апреля 2014

Суммирование в режиме реального времени, позволяющее отслеживать ход выполнения некоторого сложного задания.

$ cat numbers.txt 
1
2
3
4
5
6
7
8
9
10

$ cat numbers.txt | while read new; do total=$(($total + $new)); echo $total; done
1
3
6
10
15
21
28
36
45
55

(В этом случае нет необходимости устанавливать $total на ноль. Также вы не можете получить доступ к $ total после финиша.)

1 голос
/ 03 апреля 2017

Просто для полноты есть решение R

seq 1 10 | R -q -e "f <- file('stdin'); open(f); cat(sum(as.numeric(readLines(f))))"
1 голос
/ 17 июня 2016

Использование переменной env tmp

tmp=awk -v tmp="$tmp" '{print $tmp" "$1}' <filename>|echo $tmp|sed "s/ /+/g"|bc

tmp=cat <filename>|awk -v tmp="$tmp" '{print $tmp" "$1}'|echo $tmp|sed "s/ /+/g"|bc

Спасибо.

1 голос
/ 21 декабря 2014

Вы можете сделать это с помощью Alacon - утилиты командной строки для Alasql базы данных.

Он работает с Node.js, поэтому вам нужно установить Node.js , а затем Alasql пакет:

Чтобы вычислить сумму из стандартного ввода, вы можете использовать следующую команду:

> cat data.txt | node alacon "SELECT VALUE SUM([0]) FROM TXT()" >b.txt
1 голос
/ 16 февраля 2013

Интерпретатор lua присутствует во всех системах на основе fedora [fedora, RHEL, CentOS, korora и т. Д., Потому что он встроен в rpm-package (пакет менеджера пакетов rpm), то есть rpm-lua], и если вы хотите для изучения Луа такие проблемы идеальны (вы также справитесь с работой).

cat filname | lua -e "sum = 0;for i in io.lines() do sum=sum+i end print(sum)"

и это работает. Lua многословен, хотя, возможно, вам придется перенести несколько повторных травм от удара клавиатуры:)

0 голосов
/ 18 марта 2013
#include <iostream>

int main()
{
    double x = 0, total = 0;
    while (std::cin >> x)
        total += x;
    if (!std::cin.eof())
        return 1;
    std::cout << x << '\n';
}
0 голосов
/ 16 января 2009

Одним из простых решений было бы написать программу, которая сделает это за вас. Вероятно, это может быть сделано довольно быстро в Python, что-то вроде:

sum = 0
file = open("numbers.txt","R")
for line in file.readlines(): sum+=int(line)
file.close()
print sum

Я не тестировал этот код, но он выглядит правильно. Просто измените numbers.txt на имя файла, сохраните код в файле с именем sum.py и в консоли введите «python sum.py»

0 голосов
/ 22 октября 2013

Простой PHP

  cat numbers.txt | php -r "echo array_sum(explode(PHP_EOL, stream_get_contents(STDIN)));"
0 голосов
/ 02 октября 2013

Однострочник в Реболе:

rebol -q --do 's: 0 while [d: input] [s: s + to-integer d] print s' < infile.txt

К сожалению, вышеприведенное пока не работает в Rebol 3 ( INPUT не передает STDIN).

Итак, вот временное решение, которое также работает в Rebol 3:

rebol -q --do 's: 0 foreach n to-block read %infile.txt [s: s + n] print s'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...