Ved hjelp av awk for å summere verdiene til en kolonne, basert på verdiene til en annen kolonne

Jeg prøver å summere visse tall i en kolonne ved hjelp av awk. Jeg vil bare oppsummere kolonne 3 av «smidene» for å få totalt 212. Jeg kan oppsummere hele kolonnen ved hjelp av awk, men ikke bare «smidene». Jeg har:

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

Også bruker jeg kitt. Takk for all hjelp.

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

Svar

awk -F "|" "$1 ~ /smiths/ {sum += $3} END {print sum}" inputfilename 
  • -F -flagget setter feltseparatoren; Jeg setter det i enkelt anførselstegn fordi det er en spesiell skallkarakter.
  • Deretter gjelder $1 ~ /smiths/ følgende {kodeblokk} bare på linjer der det første feltet samsvarer med regex /smiths/.
  • Resten er den samme som koden din.

Vær oppmerksom på at siden du ikke egentlig bruker en regex her, bare en spesifikk verdi, kan du like gjerne bruk:

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

Som kontrollerer strengens likhet. Dette tilsvarer å bruke regex /^smiths$/, som nevnt i en annen svar, som inkluderer ^ anker for bare å matche starten på strengen (starten på felt 1) og $ ankeret til bare samsvarer med slutten av strengen. Ikke sikker på hvor kjent du er med regexes. De er veldig kraftige, men i dette tilfellet kan du like gjerne bruke en strengjevnhetssjekk.

Kommentarer

  • For øvrig er min favoritt-awk-referanse grymoire.com/Unix/Awk.html . Veldig nyttig side .
  • Takk @Wildcard! Jeg klarte å samle en ukomprimert størrelse på bestemte filer pent i stort zip-arkiv basert på ditt råd 🙂

Svar

En annen tilnærming er å bruke awk associative arrays, mer info her . Denne linjen gir ønsket utgang:

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

Som en bivirkning lagrer matrisen alle andre verdier:

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

Utgang:

smiths 212 denniss 100 olivert 10 

Kommentarer

  • Dette er riktig svar

Svar

Veldig bra så langt. Alt du trenger å gjøre er å legge til en velger før blokken for å legge til summen. Her sjekker vi at det første argumentet bare inneholder «smeder»:

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

Du kan forkorte dette litt ved å spesifisere feltskilleren som et alternativ. I awk er det generelt lurt å initialisere variabler på kommandolinjen:

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

Svar

Jeg foretrekker personlig å holde awk -seksjonen så enkel som mulig og gjøre så mye du kan uten den Comingled logikk utnytter ikke kraften til Unix-rørledninger og er dermed vanskeligere å forstå, feilsøke eller modifisere for nært beslektede brukssaker.

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

Svar

cat filename.txt | grep smiths | awk -F "|" "{sum+=$NF} END {print sum}" 
  • -F alternativ for å spesifisere skilletegn .
  • $NF er for «siste kolonne».

Kommentarer

  • cat og grep er unødvendige her.
  • Hvorfor er grep unødvendig @Andrey? OP vil bare legge til " smith " rader. Du ' d trenger å endre awk-setningen, ikke sant?
  • @EL ja, awk-setningen skal endres til /smiths/{...} hvis grep-samtalen ikke er der. Dette er en triviell modifikasjon, men det gir betydelige fordeler: reduserer antall kjørende prosesser, forenkler feilkontrollen og gjør koden tydeligere.

Legg igjen en kommentar

Din e-postadresse vil ikke bli publisert. Obligatoriske felt er merket med *