Başka bir sütunun değerlerini temel alarak bir sütunun değerlerini toplamak için awk kullanma


63

Kullanarak bir sütundaki belirli sayıları toplamaya çalışıyorum awk. Toplam 212 elde etmek için sadece "demirciler" in 3. sütununu toplamak istiyorum. Tüm sütunu awksadece "demirciler" kullanarak değil , toplamıyla da toplayabilirim . Sahibim:

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

Ayrıca macun kullanıyorum. Herhangi bir yardım için teşekkür ederim.

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

Yanıtlar:


81
awk -F '|' '$1 ~ /smiths/ {sum += $3} END {print sum}' inputfilename
  • -FBayrak alan ayırıcısını belirler; Özel bir kabuk karakteri olduğu için bunu tek tırnak içine koydum.
  • Ardından $1 ~ /smiths/, aşağıdaki {kod bloğu} yalnızca ilk alanın regex ile eşleştiği satırlara uygulanır /smiths/.
  • Gerisi sizin kodunuzla aynı.

Gerçekten burada bir regex kullanmadığınızdan, sadece belirli bir değere sahip olduğunuzdan, aşağıdaki kadar kolay kullanabileceğinizi unutmayın:

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

Hangi dize eşitliği kontrol eder. Bu, yalnızca dizenin başlangıcıyla (alan 1'in başlangıcı) eşleşecek olan tutturucu ve dizenin yalnızca eşleşmesi için tutturulmuş kenet /^smiths$/içeren başka bir cevapta belirtildiği gibi regex'i kullanmaya eşdeğerdir . Regex'lere ne kadar aşina olduğunuzdan emin değilim. Çok güçlüler, ancak bu durumda bir dize eşitliği kontrolünü bu kadar kolay bir şekilde kullanabilirsiniz.^$


3
Bu arada, benim en sevdiğim awk referansım grymoire.com/Unix/Awk.html . Çok yardımcı sayfa.
Wildcard

1
Teşekkürler @Wildcard! Tavsiyenize dayanarak büyük zip arşivinde sıkıştırılmamış belirli bir dosya boyutunu unzip -lv /appl/tmp/data.lar | grep documentlibrary | awk '{sum += $1} END {print sum/1024/1024}'
Pawel

15

Başka bir yaklaşım, awk birleştirici dizileri kullanmak, burada daha fazla bilgi kullanmaktır . Bu çizgi istenen çıktıyı üretir:

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

Yan etki olarak, dizi diğer tüm değerleri saklar:

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

Çıktı:

smiths 212
denniss 100
olivert 10

Bu doğru cevap
PoVa

5

Şimdiye kadar çok iyi. Tek yapmanız gereken, toplamı eklemek için bloktan önce bir seçici eklemek. Burada ilk argümanın sadece "demirci" içerdiğini kontrol ediyoruz:

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

Alan ayırıcıyı bir seçenek olarak belirleyerek bunu biraz kısaltabilirsiniz. Genelde awkdeğişkenleri komut satırından başlatmak iyi bir fikirdir:

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

0
cat filename.txt | grep smiths | awk -F '|' '{sum+=$NF} END {print sum}'
  • -F ayırıcı belirtme seçeneği.
  • $NF "son sütun" içindir.

1
catve grepburada gereksiz.
Andrey,

Grep neden @Andrey'e ihtiyaç duymuyor? OP sadece "demirci" satırları eklemek istiyor. Awk deyimini değiştirmeniz gerekebilir, değil mi?
EL,

1
@ EL evet, /smiths/{...}grep çağrısı yoksa , awk ifadesi değiştirilmelidir . Bu önemsiz bir değişikliktir, ancak önemli faydalar sağlar: Çalışan işlem sayısını azaltır, hata kontrolünü basitleştirir ve kodu daha net hale getirir.
Andrey,

0

Şahsen, awkbölümü olabildiğince basit tutmayı ve o olmadan da yapmayı olabildiğince yapmayı tercih ederim . Birleşik mantık, Unix boru hatlarının gücünden faydalanmıyor ve bu nedenle yakından ilgili kullanım durumlarını anlamak, hata ayıklamak veya değiştirmek daha zor.

cat filename.txt | perl -pe 's{.*|}{}g' | awk '{sum+=$1} END {print sum}'
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.