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)?


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

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

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.


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 }'

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

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

0

Einfach -

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

addiert die Zahlen und gibt Ihnen die Summe.


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
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.