Brug awk til at opsummere værdierne i en kolonne, baseret på værdierne i en anden kolonne

Jeg prøver at summere bestemte tal i en kolonne ved hjælp af awk. Jeg vil bare sammenfatte kolonne 3 i “smederne” for at få i alt 212. Jeg kan sammenfatte hele kolonnen ved hjælp af awk men ikke kun “smederne”. Jeg har:

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

Også jeg bruger kit. Tak for enhver hjælp.

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 flag indstiller feltadskilleren; Jeg sætter det i enkelte citater, fordi det er en særlig skalkarakter.
  • Derefter anvender $1 ~ /smiths/ følgende {kodeblok} kun på linjer, hvor det første felt matcher regex /smiths/.
  • Resten er den samme som din kode.

Bemærk, at da du ikke rigtig bruger en regex her, bare en bestemt værdi, kan du lige så let brug:

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

Hvilket kontrollerer strengens ligestilling. Dette svarer til at bruge regex /^smiths$/, som nævnt i en anden svar, som inkluderer ^ anker for kun at matche starten af strengen (starten på felt 1) og $ ankeret til kun match slutningen af strengen. Ikke sikker på, hvor bekendt du er med regexes. De er meget kraftfulde, men i dette tilfælde kan du bruge en streng lighedskontrol lige så let.

Kommentarer

  • Forresten er min favorit-awk-reference grymoire.com/Unix/Awk.html . Meget hjælpsom side .
  • Tak @Wildcard! Jeg kunne pænt samle en ukomprimeret størrelse af bestemte filer i stort zip-arkiv baseret på dit råd 🙂

Svar

En anden tilgang er at bruge awk associative arrays, mere info her . Denne linje producerer det ønskede output:

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

Som en bivirkning gemmer arrayet alle andre værdier:

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

Output:

smiths 212 denniss 100 olivert 10 

Kommentarer

  • Dette er det rigtige svar

Svar

Meget god indtil videre. Alt hvad du skal gøre er at tilføje en vælger inden blokken for at tilføje summen. Her kontrollerer vi, at det første argument kun indeholder “smede”:

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

Du kan forkorte dette en smule ved at angive feltadskilleren som en mulighed. I awk er det generelt en god ide at initialisere variabler på kommandolinjen:

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

Svar

Jeg foretrækker personligt at holde sektionen awk så enkel som muligt og gøre så meget som muligt uden det Comedled-logik udnytter ikke kraften i Unix-rørledninger og er derfor sværere at forstå, debugge eller ændre til nært beslægtede brugssager.

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 mulighed for at specificere separator .
  • $NF er til “sidste kolonne”.

Kommentarer

  • cat og grep er unødvendige her.
  • Hvorfor er grep unødvendigt @Andrey? OP ønsker kun at tilføje " smiths " rækker. Du ' har brug for at ændre awk-sætningen, ikke?
  • @EL ja, awk-sætningen skal ændres til /smiths/{...} hvis grep-opkaldet ikke er der. Dette er en triviel ændring, men det giver betydelige fordele: mindsker antallet af kørende processer, forenkler fejlkontrol og gør koden klarere.

Skriv et svar

Din e-mailadresse vil ikke blive publiceret. Krævede felter er markeret med *