Wie kann ich Zahlen in Zeilen einer Datei addieren?

24

Ich habe eine Datei, die so aussieht:

1
3
4
1
4
3
1
2

Wie kann ich die Summe daraus ermitteln (dh 1 + 3 + 4 + 1 + 4 + 3 + 1 + 2 = 19)?

Tim
quelle
1
Für den Kontext zähle ich die Anzahl der Abzeichen, die ich auf Ask Ubuntu von der Stack Exchange-API habe.
Tim
Mitcat badges.json | grep -o '"award_count":[0-9],"rank":"gold"' | grep -o [0-9]
Tim
Obwohl mir jetzt klar ist, dass die API eine badge_countMethode hat.
Tim
Wenn Sie die Ausweise aus der API zählen, kann die Sprache, in der Sie die API abfragen, dies nicht tun (Python, Javascript).
Braiam,

Antworten:

41

bcmit ein wenig hilfe von pastebekommen die zeilen in einer einzigen mit +als trennzeichen:

paste -sd+ file.txt | bc

Um die Ausgabe von grep(oder einem anderen Befehl) statt einer statischen Datei zu verwenden, übergeben Sie das grepSTDOUT von an das STDIN von paste:

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

Beispiel:

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

% paste -sd+ file.txt | bc
19

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

Wenn Sie verwenden müssen bash, können Sie ein Array verwenden, um den Dateiinhalt zu speichern und dann die Elemente zu durchlaufen, oder Sie können die Datei zeilenweise lesen und die Summe für jede Zeile berechnen. Der zweite Ansatz wäre effizienter:

$ 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
quelle
Hmm nett. Tut mir leid, die Frage zu ändern: Könnte ich diese so ändern, dass sie Grep-Ausgabe akzeptiert (oder eine Zeile wie cat file.txt | bc?)
Tim
@ Tim Überprüfen Sie meine Änderungen
heemayl
Ta, das war einfach!
Tim
2
Der Standard hat bei mir nicht funktioniert, bis ich in einer anderen Antwort herausfand, die ich verwenden musste paste -sd+ -. Bitte ändern Sie das.
Xerus
19

Du könntest auch awk benutzen. So zählen Sie die Gesamtzahl der Zeilen in * .txt- Dateien, die das Wort "Hallo" enthalten:

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

So summieren Sie einfach die Zahlen in einer Datei:

awk '{n += $1}; END{print n}' file.txt
CrazyApe84
quelle
Aber wenn diese Zeile den Wert "4" hat, zählt sie nicht 4, oder? Es wird 1 zählen.
Tim
Nein, es wird 4 zählen.
CrazyApe84
Ich möchte die Summe der Zahlen in einer Datei. Macht das das?
Tim
Ich dachte, Sie haben Ihre Frage auf die Ausgabe von grep geändert. Ich machte einige Annahmen. Ich werde hinzufügen, wie man einfach die Werte in einer Datei summiert.
CrazyApe84
2
Ja. Es ist wirklich die gleiche Antwort wie bei heemayl, aber anstelle von paste und bc wird awk verwendet, was letztendlich viel mehr Flexibilität bietet. Trotzdem ist seine Antwort gut und er war der Erste, also verdient er Ihre Stimme!
CrazyApe84
7

Verwenden Sie numsumaus der Packung num-utils!

(Möglicherweise müssen Sie sudo apt-get install num-utils)

Der Befehl numsumerledigt standardmäßig genau das, was Sie brauchen.

$ numsum file.txt 
19

Die Testnummern zeilenweise ablesen von stdin:

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

Oder aus einer Zeile lesen:

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


Mehr Dienstprogramme

Das Paket enthält einige andere Dienstprogramme für die Nummernverarbeitung, die es verdienen, bekannter zu werden:

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

und einen allgemeineren Rechnerbefehl numprocess,
der einen Ausdruck von der Befehlszeile auf Zahlen in Eingabezeilen anwendet.

Volker Siegel
quelle
1

Sie können awkeine native Linux-Anwendung zum Scannen und Verarbeiten von Dateien mit einem Muster pro Zeile verwenden. Für Ihre Frage wird dies produzieren, was Sie wollen:

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

Rohre akzeptieren auch:

cat file.txt | awk 'BEGIN { sum=0 } { sum+=$1 } END {print sum }'
gwarah
quelle
Es ist kein BEGIN{}Block erforderlich , siehe die Antwort von CrazyApe84 .
Terdon
Es ist überflüssig für dieses Problem, aber ich habe es aus didaktischen Gründen vorgezogen, es aufzunehmen.
Gwarah
Aber was lehrt es? Es ist für jedes Problem redundant, awkist nicht C, Sie müssen keine Variable festlegen, bevor Sie es verwenden. Versuchen Sie es awk 'BEGIN{print c+=1}'.
Terdon
BEGIN {}Block wurde nicht nur zum Initialisieren von Variablen entwickelt. Es nimmt an der Designspezifikation teil. Bei einigen Problemen könnte es also notwendig sein.
Gwarah
0

Dies ist eine relativ einfache Verwendung von bashSkripten.

SUM=0; for line in `cat file.txt`; do SUM=$((SUM + line)); done
zomfg_zombie
quelle
Dies ist viel einfacher und minimalistischer als die aktuelle Lösung.
Det
0

Perl-Lösung:

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

Das obige kann alle Zahlen über mehrere Dateien summieren:

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

Für mehrere Dateien, die in der Befehlszeile angegeben werden und in denen die Summe der Zahlen in einer einzelnen Datei angezeigt werden soll, können Sie Folgendes tun:

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

Einfach -

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

addiert die Zahlen und gibt Ihnen die Summe.

Sufyan Ramzan
quelle
0

Ein einfacher Ansatz besteht darin, eine integrierte Funktion Ihrer Shell zu verwenden:

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

Dies liest Ihre Datei zeilenweise, summiert und druckt das Ergebnis.

Wenn Sie eine Pipe verwenden möchten und nur die 1. Reihe verwenden, funktioniert dies folgendermaßen:

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

Das erste Element zu erhalten, geschieht folgendermaßen:

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

foo
Bastian Bittorf
quelle