Jak mogę sumować liczby na liniach w pliku


24

Mam plik, który wygląda następująco:

1
3
4
1
4
3
1
2

Jak mogę znaleźć sumę tego (tj. 1 + 3 + 4 + 1 + 4 + 3 + 1 + 2 = 19)?


1
Dla kontekstu liczę liczbę odznak, które mam na Ask Ubuntu z interfejsu API Stack Exchange.
— Tim

Zcat badges.json | grep -o '"award_count":[0-9],"rank":"gold"' | grep -o [0-9]
— Timem

Chociaż teraz zdaję sobie sprawę, że API ma badge_countmetodę.
— Tim

Jeśli liczysz odznaki z interfejsu API, język, którego używasz do wysyłania zapytań do interfejsu API, nie może tego zrobić (python, javascript)?
— Braiam

Odpowiedzi:


42

bcz niewielką pomocą, pasteaby uzyskać linie w jednym z +separatorem:

paste -sd+ file.txt | bc

Aby użyć wyniku grep(lub dowolnej innej komendy) zamiast pliku statycznego, przekaż grepSTDOUT do STDIN w paste:

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

Przykład:

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

% paste -sd+ file.txt | bc
19

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

Jeśli musisz użyć bash, możesz użyć tablicy do zapisania zawartości pliku, a następnie iteracji po elementach lub możesz odczytać plik linia po linii i wykonać sumę dla każdej linii, drugie podejście byłoby bardziej wydajne:

$ 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

Hmmm nieźle. Przepraszam, że mogę zmienić pytanie: czy mogę to zmienić, aby zaakceptować wyjście grep (lub ustawić jedną linię jak cat file.txt | bc?
— Tim

@ Tim Sprawdź moje zmiany
— heemayl

Ta, to było proste!
— Tim

2
standardowy sposób nie działał dla mnie, dopóki nie odkryłem w innej odpowiedzi, której musiałem użyć paste -sd+ -. Proszę to poprawić.
— Xerus

19

Możesz także użyć awk. Aby policzyć całkowitą liczbę wierszy w plikach * .txt zawierających słowo „cześć”:

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

Aby po prostu zsumować liczby w pliku:

awk '{n += $1}; END{print n}' file.txt

Ale jeśli ten wiersz ma wartość „4”, nie będzie liczony 4, będzie. Będzie się liczyć 1.
— Tim

Nie, to się liczy 4.
— CrazyApe84,

Chcę sumę liczb w pliku. Czy to to robi?
— Tim

Myślałem, że zmieniłeś swoje pytanie na wyjście grep. Robiłem pewne założenia. Dodam, jak po prostu zsumować wartości w pliku.
— CrazyApe84,

2
Tak. To naprawdę ta sama odpowiedź co heemayl, ale zamiast wkleić i bc używa awk, co ostatecznie daje o wiele większą elastyczność. Mimo to jego odpowiedź jest dobra i był pierwszy, więc zasługuje na twój głos!
— CrazyApe84,

7

Użyj numsumz paczki num-utils!

(Być może trzeba sudo apt-get install num-utils)

Komenda numsumdomyślnie wykonuje dokładnie to, czego potrzebujesz;

$ numsum file.txt 
19

Odczytywanie liczb testowych linia po linii z stdin:

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

Lub czytanie z jednej linii:

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


Więcej narzędzi

Pakiet zawiera inne narzędzia do przetwarzania liczb, które zasługują na większą popularność:

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

oraz bardziej ogólne polecenie kalkulatora numprocess,
które stosuje wyrażenie z wiersza poleceń do liczb w wierszach wprowadzania.


1

Możesz użyć awkrodzimej aplikacji linux przydatnej do skanowania i przetwarzania plików ze wzorem w linii. W przypadku twojego pytania wygeneruje to, co chcesz:

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

Rury są również akceptowane:

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

Nie ma potrzeby BEGIN{}blokowania, patrz odpowiedź CrazyApe84 .
— terdon

Jest zbędny w stosunku do tego problemu, ale wolałem go uwzględnić ze względu na cel dydaktyczny.
— gwarah

Ale czego to uczy? Jest redundantny dla każdego problemu, awknie jest C, nie trzeba ustawiać zmiennej przed użyciem. Spróbować awk 'BEGIN{print c+=1}'.
— terdon

BEGIN {}blok nie został zaprojektowany tylko do inicjowania zmiennych. Bierze udział w specyfikacji projektu. W przypadku niektórych problemów może to być potrzebne.
— gwarah

0

Jest to dość proste użycie bashskryptów.

SUM=0; for line in `cat file.txt`; do SUM=$((SUM + line)); done

Jest to o wiele prostsze i minimalistyczny zestaw narzędzi niż obecne rozwiązanie.
— Det

0

Rozwiązanie Perla:

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

Powyższe może sumować wszystkie liczby w wielu plikach:

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

W przypadku wielu plików podanych w wierszu poleceń, w których chcemy zobaczyć sumę liczb w poszczególnych plikach, możemy to zrobić:

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


0

Prostym podejściem jest użycie wbudowanej funkcji powłoki:

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

Spowoduje to odczytanie pliku linii, podsumowanie i wydrukowanie wyniku.

Jeśli chcesz użyć potoku i używać tylko pierwszego wiersza, działa to tak:

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

Uzyskanie pierwszego elementu odbywa się w następujący sposób:

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

foo
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.