Comment puis-je additionner des nombres sur les lignes d'un fichier


24

J'ai un fichier qui ressemble à ceci:

1
3
4
1
4
3
1
2

Comment puis-je trouver le total de cela (c'est-à-dire 1 + 3 + 4 + 1 + 4 + 3 + 1 + 2 = 19)?


1
Pour le contexte, je compte le nombre de badges que j'ai sur Ask Ubuntu à partir de l'API Stack Exchange.
Tim

Aveccat badges.json | grep -o '"award_count":[0-9],"rank":"gold"' | grep -o [0-9]
Tim

Bien que je réalise maintenant que l'API a une badge_countméthode.
Tim

Si vous comptez les badges de l'API, la langue que vous utilisez pour interroger l'API ne peut pas le faire (python, javascript)?
Braiam

Réponses:


42

bcavec un peu d'aide pastepour obtenir les lignes en une seule avec +comme séparateur:

paste -sd+ file.txt | bc

Pour utiliser la sortie de grep(ou toute autre commande) à la place d'un fichier statique, passez le grepSTDOUT du au STDIN de paste:

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

Exemple:

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

% paste -sd+ file.txt | bc
19

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

Si vous devez utiliser bash, alors vous pouvez utiliser un tableau pour enregistrer le contenu du fichier et ensuite parcourir les éléments ou vous pouvez lire le fichier ligne par ligne et faire la somme pour chaque ligne, la deuxième approche serait plus efficace:

$ 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, sympa. Désolé de changer la question: pourrais-je le modifier pour accepter la sortie grep (ou en faire une ligne comme cat file.txt | bc?
Tim

@Tim Vérifiez mes modifications
heemayl

Ta, c'était simple!
Tim

2
la méthode stdin n'a pas fonctionné pour moi jusqu'à ce que je découvre dans une autre réponse que je devais utiliser paste -sd+ -. Veuillez modifier cela.
Xerus

19

Vous pouvez également utiliser awk. Pour compter le nombre total de lignes dans les fichiers * .txt qui contiennent le mot "bonjour":

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

Pour simplement additionner les nombres dans un fichier:

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

Mais si cette ligne a la valeur "4", elle ne comptera pas 4. Il comptera 1.
Tim

Non, ça comptera 4.
CrazyApe84

Je veux le total des nombres dans un fichier. Est-ce que cela fait ça?
Tim

Je pensais que vous aviez changé votre question en sortie de grep. Je faisais quelques suppositions. J'ajouterai comment additionner simplement les valeurs dans un fichier.
CrazyApe84

2
Ouais. C'est vraiment la même réponse que celle de heemayl, mais au lieu de coller et bc, il utilise awk, ce qui donne finalement beaucoup plus de flexibilité. Pourtant, sa réponse est bonne et il était le premier donc il mérite votre vote!
CrazyApe84

7

À utiliser numsumdans l'emballage num-utils!

(Vous devrez peut-être sudo apt-get install num-utils)

La commande numsumfait exactement ce dont vous avez besoin par défaut;

$ numsum file.txt 
19

Lecture des numéros de test ligne par ligne à partir de stdin:

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

Ou en lisant une ligne:

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


Plus d'utilitaires

Le package contient quelques autres utilitaires pour le traitement des nombres qui méritent d'être mieux connus:

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

et une commande de calculatrice plus générale numprocess,
qui applique une expression de la ligne de commande aux nombres sur les lignes d'entrée.


1

Vous pouvez utiliser awkune application Linux native utile pour numériser et traiter des fichiers avec un modèle par ligne. Pour votre question, cela produira ce que vous voulez:

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

Les tuyaux sont également acceptés:

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

Pas besoin de BEGIN{}bloc, voir la réponse de CrazyApe84 .
terdon

Il est redondant à ce problème mais j'ai préféré l'inclure en raison d'un objectif didactique.
gwarah

Mais qu'est-ce que ça enseigne? Il est redondant pour chaque problème, awkn'est pas C, vous n'avez pas besoin de définir une variable avant de l'utiliser. Essayez awk 'BEGIN{print c+=1}'.
terdon

BEGIN {}Le bloc n'a pas été conçu uniquement pour initialiser des variables. Il participe aux spécifications de conception. Donc, sur certains problèmes, cela pourrait être nécessaire.
gwarah

0

Il s'agit d'une utilisation assez simple des bashscripts.

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

C'est beaucoup plus simple et le jeu d'outils minimaliste que la solution actuelle.
Det

0

Solution Perl:

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

Ce qui précède peut additionner tous les nombres sur plusieurs fichiers:

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

Pour plusieurs fichiers donnés en ligne de commande où nous voulons voir la somme des nombres dans un fichier individuel, nous pouvons le faire:

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

0

Simple -

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

additionne les chiffres et vous donne le total.


0

Une approche simple consiste à utiliser une fonction intégrée de votre shell:

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

Cela lit votre fichier en ligne, résume et imprime le résultat.

Si vous souhaitez utiliser un tuyau et utiliser uniquement la 1ère ligne, cela fonctionne comme ceci:

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

Obtenir le premier élément se fait comme ceci:

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

foo
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.