Folosind awk pentru a însuma valorile unei coloane, pe baza valorilor altei coloane

Încerc să sumez anumite numere dintr-o coloană folosind awk. Aș dori să rezum doar coloana 3 din „smiths” pentru a obține un total de 212. Pot să însumez întreaga coloană folosind awk, dar nu doar „smiths”. Am:

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

De asemenea, folosesc chit. Vă mulțumim pentru ajutor.

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

Răspuns

awk -F "|" "$1 ~ /smiths/ {sum += $3} END {print sum}" inputfilename 
  • Steagul -F setează separatorul de câmp; Am pus-o în ghilimele unice, deoarece este un personaj special de tip shell.
  • Apoi $1 ~ /smiths/ aplică următorul {bloc de cod} numai liniilor în care primul câmp corespunde regexului /smiths/.
  • Restul este același cu codul dvs.

Rețineți că, din moment ce nu utilizați cu adevărat o regex aici, doar o anumită valoare, ați putea la fel de simplu use:

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

Care verifică egalitatea șirurilor. Aceasta este echivalentă cu utilizarea regexului /^smiths$/, așa cum se menționează într-un alt răspuns, care include ^ ancora pentru a se potrivi doar cu începutul șirului (începutul câmpului 1) și cu $ numai cu potriviți sfârșitul șirului. Nu sunteți sigur cât de familiarizați cu regexurile. Acestea sunt foarte puternice, dar pentru acest caz puteți utiliza o verificare a egalității șirurilor la fel de ușor.

Comentarii

  • Apropo, referința mea preferată pentru awk este grymoire.com/Unix/Awk.html . Pagina foarte utilă .
  • Vă mulțumim @Wildcard! Am reușit să cumulez cu grijă o dimensiune necomprimată a anumitor fișiere într-o arhivă zip mare pe baza sfaturilor dvs. 🙂

Răspuns

O altă abordare este utilizarea matricilor asociative awk, mai multe informații aici . Această linie produce ieșirea dorită:

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

Ca efect secundar, matricea stochează toate celelalte valori:

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

Ieșire:

smiths 212 denniss 100 olivert 10 

Comentarii

  • Acesta este răspunsul corect

Răspuns

Foarte bine până acum. Tot ce trebuie să faceți este să adăugați un selector înainte de bloc pentru a adăuga suma. Aici verificăm dacă primul argument conține doar „smiths”:

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

Puteți scurta un pic specificând separatorul de câmp ca opțiune. În awk este, în general, o idee bună să inițializați variabile pe linia de comandă:

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

Răspunde

Personal, aș prefera să păstrez secțiunea awk cât mai simplă posibil și să faci cât de mult poți fără ea Logica combinată nu profită de puterea conductelor Unix și este astfel mai greu de înțeles, depanat sau modificat pentru cazuri de utilizare strâns legate.

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

Răspuns

cat filename.txt | grep smiths | awk -F "|" "{sum+=$NF} END {print sum}" 
  • -F opțiune pentru a specifica separatorul .
  • $NF este pentru „ultima coloană”.

Comentarii

  • cat și grep nu sunt necesare aici.
  • De ce grep nu este necesar @Andrey? OP dorește să adauge numai " smiths " rânduri. ' ar trebui să modificați instrucțiunea awk, nu?
  • @EL da, instrucțiunea awk ar trebui modificată în /smiths/{...} dacă apelul grep nu este acolo. Aceasta este o modificare banală, dar oferă beneficii semnificative: scade numărul de procese care rulează, simplifică controlul erorilor și clarifică codul.

Lasă un răspuns

Adresa ta de email nu va fi publicată. Câmpurile obligatorii sunt marcate cu *