Bagaimana saya bisa menjumlahkan angka pada baris dalam file

24

Saya punya file yang terlihat seperti ini:

1
3
4
1
4
3
1
2

Bagaimana saya dapat menemukan total dari ini (yaitu 1 + 3 + 4 + 1 + 4 + 3 + 1 + 2 = 19)?

Tim
sumber
1
Untuk konteks, saya menghitung jumlah badge yang saya miliki di Ask Ubuntu dari Stack Exchange API.
Tim
Dengancat badges.json | grep -o '"award_count":[0-9],"rank":"gold"' | grep -o [0-9]
Tim
Meskipun sekarang saya menyadari API memiliki badge_countmetode.
Tim
Jika Anda menghitung lencana dari API, bahasa yang Anda gunakan untuk meminta API tidak dapat melakukan ini (python, javascript)?
Braiam

Jawaban:

42

bcdengan sedikit bantuan dari pasteuntuk mendapatkan garis dalam satu dengan +pemisah:

paste -sd+ file.txt | bc

Untuk menggunakan output dari grep(atau perintah lain) sebagai pengganti file statis, grepkirimkan STDOUT ke STDIN dari paste:

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

Contoh:

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

% paste -sd+ file.txt | bc
19

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

Jika Anda harus menggunakan bash, maka Anda dapat menggunakan array untuk menyimpan konten file dan kemudian beralih ke elemen-elemen atau Anda dapat membaca file baris demi baris dan melakukan penjumlahan untuk setiap baris, pendekatan kedua akan lebih efisien:

$ 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
sumber
Hmm, bagus. Maaf untuk mengubah pertanyaan: dapatkah saya memodifikasi ini untuk menerima output grep (atau membuatnya menjadi satu baris seperti cat file.txt | bc?
Tim
@Tim Periksa hasil edit saya
heemayl
Ta, itu sederhana!
Tim
2
cara stdin tidak bekerja untuk saya sampai saya menemukan jawaban lain yang harus saya gunakan paste -sd+ -. Tolong ubah itu.
Xerus
19

Anda bisa menggunakan awk juga. Untuk menghitung jumlah total baris dalam file * .txt yang berisi kata "halo":

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

Untuk hanya menjumlahkan angka dalam file:

awk '{n += $1}; END{print n}' file.txt
CrazyApe84
sumber
Tetapi jika baris itu memiliki nilai "4" itu tidak akan menghitung 4 kan. Itu akan dihitung 1.
Tim
Tidak, itu akan dihitung 4.
CrazyApe84
Saya ingin total angka dalam file. Apakah ini melakukan itu?
Tim
Saya pikir Anda mengubah pertanyaan Anda menjadi keluaran grep. Saya membuat beberapa asumsi. Saya akan menambahkan cara menjumlahkan nilai dalam file.
CrazyApe84
2
Ya. Ini benar-benar jawaban yang sama dengan heemayl, tetapi alih-alih menempel dan menggunakan biksu, yang pada akhirnya memberikan lebih banyak fleksibilitas. Tetap saja, jawabannya baik dan dia yang pertama sehingga dia layak memilih Anda!
CrazyApe84
7

Gunakan numsumdari paket num-utils!

(Anda mungkin perlu sudo apt-get install num-utils)

Perintah numsumtidak hanya apa yang Anda butuhkan secara default;

$ numsum file.txt 
19

Membaca angka uji baris demi baris dari stdin:

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

Atau membaca dari satu baris:

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


Utilitas lebih banyak

Paket ini berisi beberapa utilitas lain untuk pemrosesan angka yang layak dikenal:

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

dan perintah kalkulator yang lebih umum numprocess,
yang menerapkan ekspresi dari baris perintah ke angka pada baris input.

Volker Siegel
sumber
1

Anda dapat menggunakan awk, aplikasi linux asli yang berguna untuk memindai dan memproses file dengan pola per baris. Untuk pertanyaan Anda, ini akan menghasilkan apa yang Anda inginkan:

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

Pipa juga menerima:

cat file.txt | awk 'BEGIN { sum=0 } { sum+=$1 } END {print sum }'
gwarah
sumber
Tidak perlu untuk BEGIN{}blok, lihat jawaban CrazyApe84 .
terdon
Itu berlebihan untuk masalah ini, tetapi saya lebih suka untuk memasukkannya karena tujuan didaktik.
gwarah
Tapi apa yang diajarkannya? Itu berlebihan untuk setiap masalah, awkbukan C, Anda tidak perlu mengatur variabel sebelum menggunakannya. Coba awk 'BEGIN{print c+=1}'.
terdon
BEGIN {}blok tidak dirancang hanya untuk menginisialisasi variabel. Ini mengambil bagian pada spesifikasi desain. Jadi, pada beberapa masalah bisa dibutuhkan.
gwarah
0

Ini adalah penggunaan bashskrip yang cukup sederhana .

SUM=0; for line in `cat file.txt`; do SUM=$((SUM + line)); done
zomfg_zombie
sumber
Ini jauh lebih sederhana dan toolset yang minimalis daripada solusi saat ini.
Det
0

Solusi Perl:

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

Di atas dapat menjumlahkan semua angka di beberapa file:

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

Untuk beberapa file yang diberikan pada command-line di mana kita ingin melihat jumlah angka dalam file individual kita dapat melakukan ini:

$ 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
sumber
0

Sederhana -

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

menambahkan angka-angka dan memberi Anda total.

Sufyan Ramzan
sumber
0

Pendekatan sederhana adalah dengan menggunakan fitur bawaan shell Anda:

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

Ini membaca file Anda secara linier, merangkum dan mencetak hasilnya.

Jika Anda ingin menggunakan pipa dan hanya menggunakan baris pertama, ia berfungsi seperti ini:

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

Mendapatkan elemen pertama dilakukan seperti ini:

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

foo
Bastian Bittorf
sumber