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

Tim
la source
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
heemayl
la source
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
CrazyApe84
la source
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.

Volker Siegel
la source
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 }'
gwarah
la source
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
zomfg_zombie
la source
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
Sergiy Kolodyazhnyy
la source
0

Simple -

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

additionne les chiffres et vous donne le total.

Sufyan Ramzan
la source
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
Bastian Bittorf
la source