Zählen Sie die Summe jeder Spalte in einer Datei


9

In einer Datei mit unterschiedlicher Anzahl von Spalten, die durch Leerzeichen '' begrenzt sind, wird die Summe der Spalten gezählt. Ein Beispiel würde die Notwendigkeit zeigen:

File A:

1 2 
2 3
4 5 6 
1 1 1 5

Dann wäre die Ausgabe:

  • für Spalte 1 (1 + 2 + 4 + 1) = 8
  • für Spalte 2 ist 11
  • für Spalte 3 ist 7
  • für Spalte 4 ist 5

Antworten:


12

Verwenden von awk

awk '{for (i=1;i<=NF;i++) sum[i]+=$i;}; END{for (i in sum) print "for column "i" is " sum[i];}' FileA
for column 1 is 8
for column 2 is 11
for column 3 is 7
for column 4 is 5

Gute Verwendung von Arrays, obwohl ich denke, dass es vereinfacht werden kann, nur die Summe zu zählen und sie sofort zu
drucken

Dies ist in der Tat die beste Antwort hier.
Kos

5

Verwenden Sie numsumfür diese Aufgabe und trennen Sie zwischen Datenverarbeitung und Ausgabe der Ergebnisse.

Installieren num-utils, wir brauchennumsum

sudo apt-get install num-utils

Und fangen Sie mit an

numsum -c <your_file_name>

Beispiel

$ cat "File A"
1 2 
2 3
4 5 6 
1 1 1 5

$ numsum -c "File A"
8 11 7 5

oder mit Ihrem gewünschten Format:

$ numsum -c "File A" | awk '{for(i=1;i<=NF;i++) {print "for column "i" is "$i}}'
for column 1 is 8
for column 2 is 11
for column 3 is 7
for column 4 is 5

von man numsum

-c      Print out the sum of each column.

Beispiele aus man numsum

EXAMPLES

   Add up the 1st, 2nd and 5th columns only.

       $ numsum -c -x 1,2,5 columns
       15 40 115

   Add up the rows of numbers of a file.

        $ numsum -r columns
        55
        60
        65
        70
        75

3
#!/bin/sh

while read a b c d; do
    col1=$((col1 + a))
    col2=$((col2 + b))
    col3=$((col3 + c))
    col4=$((col4 + d))
done < File_A

echo $col1 $col2 $col3 $col4

Sie können wahrscheinlich sagen (( col1 += a )), etc. Auch echo "..."ist sicherer, sowiewhile IFS= read -r ...
fedorqui

@fedorqui kann echoauf diese Weise sicher verwendet werden, um Zahlen, $IFSStandardeinstellungen bei Leerzeichen und Zahlen, die voraussichtlich Zahlen sind, wiederzugeben , sodass keine Notwendigkeit besteht, sich mit Backslashes zu befassen. Der einzige Nachteil dieser Antwort ist die Notwendigkeit, die Anzahl der Spalten vor der Ausführung zu kennen.
Kos

@kos Sie können nie wissen, wie eine Eingabedatei sein kann. Und obwohl das OP nur Zahlen erwähnt, ist es immer eine gute Praxis, sich auf das Schlimmste vorzubereiten. Siehe Wie kann ich eine Datei (Datenstrom, Variable) Zeile für Zeile (und / oder Feld für Feld) lesen? für eine großartige Erklärung.
Fedorqui

@fedorqui Nach deiner eigenen Aussage habe ich gelernt, dass dies nicht diskutiert wurde; Wenn Sie Punkte machen möchten, unter der Annahme, dass die Eingabedatei etwas anderes als Zahlen enthalten könnte, fehlt Ihnen der offensichtliche Teil: Überprüfen, ob es sich bei dem Gelesenen um eine Zahl handelt. Das Hinzufügen von Zeichenfolgen und echo "[...]"das korrekte Drucken dessen, was Sie nicht ausgeben möchten, macht keinen Sinn.
Kos

@kos Man kann natürlich sagen echo $varund while read a b ces funktioniert hier. Sie werden sich jedoch daran gewöhnen, es schwach zu schreiben, und eines Tages werden Sie seltsame Fehler bei der Verarbeitung einer komplexeren Datei erhalten. Dann werden Sie feststellen, dass das Zitieren von Variablen und das Verwenden while IFS= read -r ...sicherer war und Sie sagen: "Oh ja, Fedorqui hatte Recht, ich hoffe, ich könnte ihn haben, um ihn zu umarmen, um Dankbarkeit zu zeigen!".
Fedorqui

3

Nach den Kommentaren zu Ihrer eigenen Antwort zu urteilen, möchten Sie jeweils nur die Summe einer Spalte. Wenn ja, ist hier ein nicht-awk-Weg, um es zu tun:

cut -d' ' -f3 FileA | grep . | paste -s -d+ | bc

wo Sie das durch die 3Spaltennummer ersetzen würden, die Sie interessiert.


0

Hier ist ein einzeiliger Perl-Skriptansatz. Dies beruht auf der Verwendung eines -aFlags, das die automatische Aufteilung der aktuell gelesenen Zeile mit dem -nFlag in ein Array ermöglicht @F. Alles, was wir tun müssen, ist, diese Elemente zu durchlaufen und sie ihrem jeweiligen Index im $sumArray hinzuzufügen. Somit ist effektiv jedes Array-Element eine Summe für die jeweilige Spalte. Schließlich drucken wir das Ergebnis innerhalb des ENDCodeblocks.

$ perl -lane '$j=0;foreach $i (@F){$sum[$j]+=$i; $j+=1;}; END{print join("\n",@sum)} ' input.txt                                                     
8
11
7
5

Alternativ finden Sie hier einen vollständigen Perl-Skriptansatz. Es basiert darauf, jede Zeile in ein Array aufzuteilen und über jedes Element in diesem Array zu iterieren, wobei jede Zahl zu ihrem jeweiligen Besitz im @sumsArray hinzugefügt wird. Das Skript druckt jede Zeile aus und erstellt dann einen Bericht für jede Spalte. Drucken jeder Zeile kann entfernt werden , indem #vorprintf("%s",$line);

#!/usr/bin/env perl
use strict;
use warnings;

open(my $fh,"<",$ARGV[0]); 
my $i = 0;
my @sums;

while(my $line = <$fh>) { 
    printf("%s",$line);
    my @nums = split(" ",$line);
    my $j = 0;
    foreach my $num (@nums){
        $sums[$j] += $num;
        $j += 1;
    }

}

my $k = 0;
foreach my $sum (@sums){
    printf("- column %d sum: %d\n",$k,$sum);
    $k+=1;
}

close($fh);

Die Verwendung ist einfach chmod +x ./sum_columns.pl && ./sum_columns.pl input.txt. Zum Beispiel:

$ ./sum_columns_2.pl input.txt                                                                                                                       
1 2 
2 3
4 5 6 
1 1 1 5
- column 0 sum: 8
- column 1 sum: 11
- column 2 sum: 7
- column 3 sum: 5

-2

Eine einfache Lösung:

awk '{sum += $i} END {print sum}' file

Ersetzen Sie i durch die Spaltennummer, zum Beispiel Spalte1:

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

Ausgabe ist:

8

3
Dadurch erhalten Sie nur eine Spalte. Sie erfüllen nicht Ihre eigenen Spezifikationen.
Oli

Ich habe nicht angegeben, dass ich alle Ergebnisse in demselben Befehl haben möchte. Plus diese Antwort brauchen nur eine Schleife und es ist perfekt
Maythux

Warum also Downvoting?
Maythux
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.