Как я генерирую рабочее кумулятивное общее количество чисел в текстовом файле?

У меня есть текстовый файл с 2 миллионами строк. Каждая строка имеет положительное целое число. Я пытаюсь сформировать вид таблицы частот вещи.

Входной файл:

3
4
5
8

Вывод должен быть:

3
7
12
20

Как я иду о выполнении этого?

8
задан 2 February 2017 в 16:04

10 ответов

С awk:

awk '{total += $0; $0 = total}1'

$0 текущая строка. Так, для каждой строки я добавляю его к total, установите строку на новое total, и затем запаздывание 1 awk ярлык - он печатает текущую строку для каждого истинного условия, и 1 поскольку условие оценивает к истинному.

17
ответ дан 23 November 2019 в 05:21

В Баш:

#! /bin/bash

file="YOUR_FILE.txt"

TOTAL=0
while IFS= read -r line
do
    TOTAL=$(( TOTAL + line ))
    echo $TOTAL
done <"$file"
8
ответ дан 23 November 2019 в 05:21

Для печати частичных сумм целых чисел, данных по стандарту, вводит тот на строку:

#!/usr/bin/env python3
import sys

partial_sum = 0
for n in map(int, sys.stdin):
    partial_sum += n
    print(partial_sum)

Выполнимый пример .

, Если по некоторым причинам команда является слишком медленной; Вы могли использовать программу C:

#include <stdint.h>
#include <ctype.h>
#include <stdio.h>

int main(void)
{
  uintmax_t cumsum = 0, n = 0;
  for (int c = EOF; (c = getchar()) != EOF; ) {
    if (isdigit(c))
      n = n * 10 + (c - '0');
    else if (n) { // complete number
      cumsum += n;
      printf("%ju\n", cumsum);
      n = 0;
    }
  }
  if (n)
    printf("%ju\n", cumsum + n);
  return feof(stdin) ? 0 : 1;
}

, Чтобы создать его и работать, введите:

$ cc cumsum.c -o cumsum
$ ./cumsum < input > output

Выполнимый пример .

UINTMAX_MAX 18446744073709551615 .

код C несколько раз быстрее, чем команда awk на моей машине для входного файла, сгенерированного:

#!/usr/bin/env python3
import numpy.random
print(*numpy.random.random_integers(100, size=2000000), sep='\n')
6
ответ дан 23 November 2019 в 05:21

Вы, вероятно, хотите что-то вроде этого:

sort -n <filename> | uniq -c | awk 'BEGIN{print "Number\tFrequency"}{print $2"\t"$1}'

Объяснение команды:

  • sort -n <filename> | uniq -c виды вход и возвраты таблица частот
  • | awk 'BEGIN{print "Number\tFrequency"}{print $2"\t"$1}' превращает вывод в более хороший Пример Формата

:
Входной Файл list.txt:

4
5
3
4
4
2
3
4
5

команда:

$ sort -n list.txt | uniq -c | awk 'BEGIN{print "Number\tFrequency"}{print $2"\t"$1}'
Number  Frequency
2   1
3   2
4   4
5   2
5
ответ дан 23 November 2019 в 05:21

Простая острота Bash:

x=0 ; while read n ; do x=$((x+n)) ; echo $x ; done < INPUT_FILE

x накопленная сумма всех чисел от текущей строки и выше.
n число в текущей строке.

Мы циклично выполняемся по всем строкам n из INPUT_FILE и добавляем их числовое значение к нашей переменной x и печать, которые суммируют во время каждого повторения.

Bash является немного медленным здесь, хотя, можно ожидать, что это будет обтекать 20-30 секунд для файла с 2 миллионами записей, не печатая вывод к консоли (который еще медленнее, независим от метода, который Вы используете).

3
ответ дан 23 November 2019 в 05:21

Аналогично ответу @ steeldriver, но с немного менее загадочным bc:

sed 's/.*/a+=&;a/' input | bc

Приятно, что в bcdc) есть калькуляторы произвольной точности, поэтому никогда не переполнится и не потеряет точность по сравнению с целыми числами.

Выражение sed преобразует входные данные в:

a+=3;a
a+=4;a
a+=5;a
a+=8;a

Это затем оценивается с помощью bc. Переменная a bc автоматически инициализируется равной 0. Каждая строка увеличивает a, а затем явно печатает ее.

3
ответ дан 23 November 2019 в 05:21

В сценарии Python:

#!/usr/bin/env python3
import sys

f = sys.argv[1]; out = sys.argv[2]

n = 0

with open(out, "wt") as wr:
    with open(f) as read:
        for l in read:
            n = n + int(l); wr.write(str(n)+"\n")

Использовать

  • Скопируйте сценарий в пустой файл, сохраните его как add_last.py
  • Выполните его с исходным файлом и предназначенным выходным файлом как аргументы:

    python3 /path/to/add_last.py <input_file> <output_file>
    

Объяснение

Код довольно читаем, но подробно:

  • Открытый выходной файл для записи результатов

    with open(out, "wt") as wr:
    
  • Открытый входной файл для чтения на строку

    with open(f) as read:
        for l in read:
    
  • Считайте строки, добавив значение новой строки к общему количеству:

    n = n + int(l)
    
  • Запишите результат в выходной файл:

    wr.write(str(n)+"\n")
    
9
ответ дан 23 November 2019 в 05:21

Только для забавы

$ sed 'a+p' file | dc -e0 -
3
7
12
20

Это работает путем добавления +p к каждой строке входа и затем передаче результата к dc калькулятор, где

   +      Pops two values off the stack, adds them, and pushes the result.
          The precision of the result is determined only by the values  of
          the arguments, and is enough to be exact.

затем

   p      Prints  the  value on the top of the stack, without altering the
          stack.  A newline is printed after the value.

-e0 нажатия аргумента 0 на dc стек для инициализации суммы.

9
ответ дан 23 November 2019 в 05:21

Можно сделать это в энергии. Откройте файл и введите следующие нажатия клавиш:

qaqqayiwj@"<C-a>@aq@a:wq<cr>

Отметьте это <C-a> на самом деле ctrl-a, и <cr> возврат каретки, т.е. ввести кнопка.

Вот то, как это работает. Прежде всего мы хотим убрать регистр так, чтобы он не имел никаких побочных эффектов на первом разе через. Это просто qaq. Затем мы делаем следующее:

qa                  " Start recording keystrokes into register 'a'
  yiw               " Yank this current number
     j              " Move down one line. This will break the loop on the last line
      @"            " Run the number we yanked as if it was typed, and then
        <C-a>       " increment the number under the cursor *n* times
             @a     " Call macro 'a'. While recording this will do nothing
               q    " Stop recording
                @a  " Call macro 'a', which will call itself creating a loop

После того, как этот рекурсивный макрос сделан, работая, мы просто звоним :wq<cr> сохранить и выйти.

5
ответ дан 23 November 2019 в 05:21

Острота Perl:

$ perl -lne 'print $sum+=$_' input.txt                                                                
3
7
12
20

С 2,5 миллионами строк чисел требуется приблизительно 6,6 секунд для обработки:

$ time perl -lne 'print $sum+=$_' large_input.txt > output.txt                                        
    0m06.64s real     0m05.42s user     0m00.09s system

$ wc -l large_input.txt
2500000 large_input.txt
5
ответ дан 23 November 2019 в 05:21

Другие вопросы по тегам:

Похожие вопросы: