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