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


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

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

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.


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

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

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

0

Sederhana -

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

menambahkan angka-angka dan memberi Anda total.


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
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.