Använda awk för att summera värdena för en kolumn, baserat på värdena för en annan kolumn

Jag försöker summera vissa nummer i en kolumn med awk. Jag vill summera bara kolumn 3 i ”smederna” för att få totalt 212. Jag kan summera hela kolumnen med awk men inte bara ”smederna”. Jag har:

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

Jag använder också kitt. Tack för all 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 -flaggan ställer in fältseparatorn; Jag lägger det i enstaka citat eftersom det är en speciell skalkaraktär.
  • Sedan tillämpar $1 ~ /smiths/ följande {kodblock} endast på rader där det första fältet matchar regex /smiths/.
  • Resten är densamma som din kod.

Observera att eftersom du inte verkligen använder en regex här, bara ett specifikt värde, kan du lika gärna användning:

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

Vilket kontrollerar stränglikhet. Detta motsvarar att använda regex /^smiths$/, som nämnts i en annan svar, som inkluderar ^ ankare för att endast matcha början på strängen (början av fält 1) och $ ankare till endast matcha slutet av strängen. Inte säker på hur bekant du är med regexes. De är väldigt kraftfulla, men i det här fallet kan du använda en strängjämnhetskontroll lika lätt.

Kommentarer

  • Förresten är min favorit-awk-referens grymoire.com/Unix/Awk.html . Mycket hjälpsam sida .
  • Tack @Wildcard! Jag kunde prydligt samla en okomprimerad storlek på vissa filer i stort zip-arkiv baserat på ditt råd 🙂

Svar

Ett annat tillvägagångssätt är att använda awk associativa arrayer, mer info här . Denna rad ger önskad utgång:

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

Som en bieffekt lagrar arrayen alla andra värden:

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

Output:

smiths 212 denniss 100 olivert 10 

Kommentarer

  • Detta är rätt svar

Svar

Mycket bra hittills. Allt du behöver göra är att lägga till en väljare före blocket för att lägga till summan. Här kontrollerar vi att det första argumentet endast innehåller ”smiths”:

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

Du kan förkorta det lite genom att ange fältseparatorn som ett alternativ. I awk är det i allmänhet en bra idé att initialisera variabler på kommandoraden:

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

Svar

Jag personligen föredrar att hålla avsnittet awk så enkelt som möjligt och göra så mycket du kan utan det Comedled-logik utnyttjar inte kraften i Unix-rörledningar och är därför svårare att förstå, felsöka eller modifiera för närbesläktade användningsfall.

Svar

cat filename.txt | grep smiths | awk -F "|" "{sum+=$NF} END {print sum}" 
  • -F alternativ för att ange separator .
  • $NF är för ”sista kolumnen”.

Kommentarer

  • cat och grep är onödiga här.
  • Varför är grep onödigt @Andrey? OP vill bara lägga till " smiths " rader. Du ' du behöver ändra awk-uttalandet, eller hur?
  • @EL ja, awk-uttalandet bör ändras till /smiths/{...} om grep-samtalet inte finns där. Detta är en triviell modifiering, men det ger betydande fördelar: minskar antalet pågående processer, förenklar felkontrollen och gör koden tydligare.

Lämna ett svar

Din e-postadress kommer inte publiceras. Obligatoriska fält är märkta *