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
undgrep
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.