Verwenden von awk zum Summieren der Werte einer Spalte basierend auf den Werten einer anderen Spalte

Ich versuche, bestimmte Zahlen in einer Spalte mit awk. Ich möchte nur Spalte 3 der „Schmiede“ summieren, um insgesamt 212 zu erhalten. Ich kann die gesamte Spalte mit awk summieren, aber nicht nur mit den „Schmieden“. Ich habe:

awk "BEGIN {FS = "|"} ; {sum+=$3} END {print sum}" filename.txt 

Außerdem verwende ich Kitt. Vielen Dank für jede Hilfe.

smiths|Login|2 olivert|Login|10 denniss|Payroll|100 smiths|Time|200 smiths|Logout|10 

Antwort

awk -F "|" "$1 ~ /smiths/ {sum += $3} END {print sum}" inputfilename 
  • Das Flag -F setzt das Feldtrennzeichen. Ich habe es in einfache Anführungszeichen gesetzt, weil es ein spezielles Shell-Zeichen ist.
  • Dann wendet $1 ~ /smiths/ den folgenden {Codeblock} nur auf Zeilen an, in denen das erste Feld mit dem regulären Ausdruck /smiths/ übereinstimmt.
  • Der Rest ist der gleiche wie Ihr Code.

Beachten Sie, dass Sie, da Sie hier nicht wirklich einen regulären Ausdruck verwenden, sondern nur einen bestimmten Wert, dies genauso einfach tun können Verwenden Sie:

awk -F "|" "$1 == "smiths" {sum += $3} END {print sum}" inputfilename 

Überprüft die Zeichenfolgengleichheit. Dies entspricht der Verwendung des regulären Ausdrucks /^smiths$/, wie in einem anderen erwähnt Antwort, die den Anker ^ enthält, der nur mit dem Anfang der Zeichenfolge (dem Anfang von Feld 1) übereinstimmt, und den Anker $ nur mit Passen Sie an das Ende der Zeichenfolge an. Sie sind sich nicht sicher, wie gut Sie mit regulären Ausdrücken vertraut sind. Sie sind sehr leistungsfähig. In diesem Fall können Sie jedoch genauso einfach eine Überprüfung der Zeichenfolgengleichheit verwenden.

Kommentare

  • Übrigens ist meine bevorzugte awk-Referenz grymoire.com/Unix/Awk.html . Sehr hilfreiche Seite
  • Vielen Dank an @Wildcard! Ich konnte eine unkomprimierte Größe bestimmter Dateien in einem großen Zip-Archiv basierend auf Ihrem Rat ordentlich zusammenfassen 🙂

Antwort

Ein anderer Ansatz besteht darin, awk assoziative Arrays zu verwenden, weitere Informationen hier . Diese Zeile erzeugt die gewünschte Ausgabe:

awk -F "|" "{a[$1] += $3} END{print a["smiths"]}" filename.txt 

Als Nebeneffekt speichert das Array alle anderen Werte:

awk -F "|" "{a[$1] += $3} END{for (i in a) print i, a[i]}" filename.txt 

Ausgabe:

smiths 212 denniss 100 olivert 10 

Kommentare

  • Dies ist die richtige Antwort

Antwort

Bisher sehr gut. Alles, was Sie tun müssen, ist, vor dem Block einen Selektor hinzuzufügen, um die Summe hinzuzufügen. Hier überprüfen wir, ob das erste Argument nur „Schmiede“ enthält:

awk "BEGIN {FS = "|"} ; $1 ~ /^smiths$/ {sum+=$3} END {print sum}" 

Sie können dies etwas verkürzen, indem Sie das Feldtrennzeichen als Option angeben. In awk ist es im Allgemeinen eine gute Idee, Variablen in der Befehlszeile zu initialisieren:

awk -F"|" "$1 ~ /^smiths$/ {sum+=$3} END {print sum}" 

Antwort

Ich persönlich würde es vorziehen, den Abschnitt awk so einfach wie möglich zu halten und so viel wie möglich ohne ihn zu tun Die Comingled-Logik nutzt die Leistung von Unix-Pipelines nicht aus und ist daher für eng verwandte Anwendungsfälle schwerer zu verstehen, zu debuggen oder zu ändern.

cat filename.txt | perl -pe "s{.*|}{}g" | awk "{sum+=$1} END {print sum}" 

Antwort

cat filename.txt | grep smiths | awk -F "|" "{sum+=$NF} END {print sum}" 
  • -F Option zum Angeben eines Trennzeichens .
  • $NF steht für „letzte Spalte“.

Kommentare

  • cat und grep sind hier nicht erforderlich.
  • Warum wird grep @Andrey nicht benötigt? OP möchte nur " Schmiede " Zeilen hinzufügen. Sie ' müssten die awk-Anweisung ändern, oder?
  • @EL ja, die awk-Anweisung sollte in /smiths/{...} wenn der grep-Aufruf nicht vorhanden ist. Dies ist eine triviale Änderung, bietet jedoch erhebliche Vorteile: Verringert die Anzahl der ausgeführten Prozesse, vereinfacht die Fehlerkontrolle und macht den Code klarer.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.