Como buscar números de um arquivo e calcular usando o shell script [closed]

1

Eu tenho um arquivo chamado numbers.txt. Que contém alguns números como este

1568
14578
2365
41655
9965
...
...

Eu preciso pegar a soma desses números. Como posso pegar isso usando um script de shell?

    
por Dinesh Dhananjayan 08.07.2015 / 11:17

6 respostas

5

Se o seu arquivo é enorme (por exemplo, seq 1 100000000 > numbers.txt ), as ferramentas tradicionais começam a desmoronar.

  • awk '{s+=} END {print s} leva 34s mas "0%" RAM (não tenho certeza se isso é preciso)
  • perl -nle '$sum += $_ } END { print $sum' numbers.txt levou 27s e uma pequena quantidade de RAM.
  • Jacob's Python leva 47s e 6GB de RAM (e 23s quando executado com pypy , mesma RAM)
  • numsum era horrível ; demorou 9m43s e 14GB de RAM para dar um número exponencial (os outros responderam com inteiros longos)
  • Pure Bash levaria sempre-e-um-dia para loop por eles, então eu não estou tentando

A alternativa eu ofereço uma resposta que pode adicionar cem milhões de inteiros em 6,4 segundos ...

... Mas está escrito em C. Easy C. Não há requisitos estranhos para construir, ou grau necessário para compreendê-lo, mas você tem que compilá-lo e o nome do arquivo é codificado nele (o que você poderia corrigir) .. .

#include <stdio.h>

int main(void) {
    FILE *fp;

    char line[100];
    unsigned long int total = 0;

    fp = fopen("numbers.txt", "r");

    while (fgets(line, 100, fp) != NULL) {
        total += atoi(line);
    }
    fclose(fp);

    printf("%li\n", total);

    return 0;
}

Salve como algo como add.c , execute make add e, em seguida, ./add para executar.

    
por Oli 08.07.2015 / 12:43
1

Usando perl e assumindo um delimitador de espaço:

perl -MList::Util=sum -ne 'print sum(split())."\n"' numbers.txt

Para um uso de , delimitador:

perl -MList::Util=sum -ne 'print sum(split(/,/))."\n"' numbers.txt

Mas prefira este comando se eles estiverem em sua própria linha:

perl -nle '$sum += $_ } END { print $sum'
    
por Sylvain Pineau 08.07.2015 / 11:46
1

Usando awk

awk -F' ' '{for (i=1;i<=NF;i++) {sum+=$i;} print sum}' <your_file> | tail -1

Se houver outro delimitador além de space , use -F'<your_delimiter>' , por exemplo: -F':'

Usando numsum ( sudo apt-get install num-utils )

numsum -r <your_file> | numsum 

Se houver outro delimitador além de space , use -s <your_delimiter> , por exemplo: -s ':'

Exemplo

% awk '{for (i=1;i<=NF;i++) {sum+=$i;} print sum}' foo         
70131
106625020

% awk '{for (i=1;i<=NF;i++) {sum+=$i;} print sum}' foo | tail -1
106625020

% numsum -r foo | numsum
106625020

% awk '{for (i=1;i<=NF;i++) {sum+=$i;} print sum}' bar | tail -1
70131

% numsum -r foo | numsum
70131

% cat foo
1568 14578 2365 41655 9965
7673 8273923 98273293

% cat bar
1568
14578
2365
41655
9965
    
por A.B. 08.07.2015 / 11:38
1

Para arquivos de entrada separados por linha, o seguinte código awk funciona bem:

  

awk '{s+=} END {print s}' numbers.txt

É relatado que, com algumas versões de awk , pode haver alguns comportamentos inesperados se a soma for maior que 2147483647.

Consulte esta resposta e seus comentários.

    
por Ron 08.07.2015 / 12:23
0

Usando bc:

paste -sd"+" file | bc
    
por Guru 08.07.2015 / 13:35
0

Em python:

python -c "print(sum(int(n) for n in open('f').read().split()))"

em que f é o arquivo (+ caminho) entre aspas (simples), por exemplo:

python -c "print(sum(int(n) for n in open('/home/jacob/Bureaublad/file.txt').read().split()))"

O delimitador pode ser alterado na seção .split() . Se, e. o delimitador é uma vírgula, set: .split(',') . Por padrão, os números são divididos por \n e " " .

Explicação:

open('f').read().split()

lê o arquivo, divide-o em números (como strings)

(int(n) for n in...

converte as strings em números

print(sum(...

finalmente, soma os números encontrados e imprime o resultado

O teste

O resultado em um arquivo:

1 2 3 4 5 200 2345

2560

Mas também; desde split() divide em \n também:

1 
2
3
4
5
200
2345

2560

EDITAR

Embora uma competição com a resposta de Oli sobre velocidade e recursos fosse um erro fatal, SE o arquivo seria enorme, pelo menos no uso de recursos, o roteiro abaixo ofereceria uma melhoria importante. Embora o script seja mais rápido que o de uma linha em minha resposta original, a maior melhoria está no uso de memória.

#!/usr/bin/env python3
import sys
total = 0
with open(sys.argv[1]) as lines:
    for l in lines:
        total = total+int(l)
print(total)

Salve-o como addnumbers.py , execute-o com o textfile como argumento:

python3 <script> <file>
    
por Jacob Vlijm 08.07.2015 / 11:39