2009-03-04 9 views
1

Ben şöyle bir:bir günlük dosyası üzerinde hesaplama gerçekleştirmek için nasıl

I, [2009-03-04T15:03:25.502546 #17925] INFO -- : [8541, 931, 0, 0] 
I, [2009-03-04T15:03:26.094855 #17925] INFO -- : [8545, 6678, 0, 0] 
I, [2009-03-04T15:03:26.353079 #17925] INFO -- : [5448, 1598, 185, 0] 
I, [2009-03-04T15:03:26.360148 #17925] INFO -- : [8555, 1747, 0, 0] 
I, [2009-03-04T15:03:26.367523 #17925] INFO -- : [7630, 278, 0, 0] 
I, [2009-03-04T15:03:26.375845 #17925] INFO -- : [7640, 286, 0, 0] 
I, [2009-03-04T15:03:26.562425 #17925] INFO -- : [5721, 896, 0, 0] 
I, [2009-03-04T15:03:30.951336 #17925] INFO -- : [8551, 4752, 1587, 1] 
I, [2009-03-04T15:03:30.960007 #17925] INFO -- : [5709, 5295, 0, 0] 
I, [2009-03-04T15:03:30.966612 #17925] INFO -- : [7252, 4928, 0, 0] 
I, [2009-03-04T15:03:30.974251 #17925] INFO -- : [8561, 4883, 1, 0] 
I, [2009-03-04T15:03:31.230426 #17925] INFO -- : [8563, 3866, 250, 0] 
I, [2009-03-04T15:03:31.236830 #17925] INFO -- : [8567, 4122, 0, 0] 
I, [2009-03-04T15:03:32.056901 #17925] INFO -- : [5696, 5902, 526, 1] 
I, [2009-03-04T15:03:32.086004 #17925] INFO -- : [5805, 793, 0, 0] 
I, [2009-03-04T15:03:32.110039 #17925] INFO -- : [5786, 818, 0, 0] 
I, [2009-03-04T15:03:32.131433 #17925] INFO -- : [5777, 840, 0, 0] 

Ben parantez içinde 2. ortalamasını ve 3. alanları hesaplayan bir kabuk komut dosyası oluşturmak istiyorum (840 ve Son örnekte 0.) Daha da zor bir soru: 3. alanın ortalamasını sadece sonuncu 0 değilken almak mümkün mü?

Bir komut dosyası oluşturmak için Ruby veya başka bir dili kullanabileceğimi biliyorum, ancak bunu Bash içinde yapmak istiyorum. Böyle bir betiğin nasıl oluşturulacağına dair kaynak veya ipucu ile ilgili iyi öneriler yardımcı olacaktır.

+0

awk yapmak için önemsiz olacaktır. Bu "bash içinde yapıyor" olarak sayılır mı? – Eddie

cevap

1

benim :) StackOverflow denemek yapar sırf ben burada çok IM üzerinden size yapıştırılan cevap Gönderme

# replace $2 with the column you want to avg; 
awk '{ print $2 }' | perl -ne 'END{ printf "%.2f\n", $total/$n }; chomp; $total+= $_; $n++' < log 
6

Kullanım bash ve awk: (orijinal veriler için)

cat file | sed -ne 's:^.*INFO.*\[\([0-9, ]*\)\][ \r]*$:\1:p' | awk -F ' *, *' '{ sum2 += $2 ; sum3 += $3 } END { if (NR>0) printf "avg2=%.2f, avg3=%.2f\n", sum2/NR, sum3/NR }'

Örnek çıktı:

avg2=2859.59, avg3=149.94

Tabii ki, cat'u kullanmanız gerekmiyor, okunaklı olması ve giriş verilerinin herhangi bir borudan gelebileceğini göstermek için orada yer alıyor; Var olan bir dosyada işlem yapmanız gerekiyorsa, doğrudan sed -ne '...' file | ...'u çalıştırın. aşağıdaki gibi


DÜZENLEME

Eğer gawk (GNU awk) erişimi varsa, sed ihtiyacını ortadan kaldırabilir:

cat file | gawk '{ if(match($0, /.*INFO.*\[([0-9, ]*)\][ \r]*$/, a)) { cnt++; split(a[1], b,/*, */); sum2+=b[2]; sum3+=b[3] } } END { if (cnt>0) printf "avg2=%.2f, avg3=%.2f\n", sum2/cnt, sum3/cnt }'

aynı sözleri yeniden. cat geçerlidir.

açıklama biraz:

  • sed yalnızca sonunda rakam, boşluklar ve köşeli parantezler arasında virgül herhangi bir kombinasyonu ile devam bilgilerini içeren normal ifade (çizgilerine uyar, çizgiler (-n ... :p kombinasyonu) yazdırır sondaki boşluklara ve CR'ye izin veren çizgi); 8541, 931, 0, 0
: Bu tür çizgi eşleşirse, sadece benziyor ( :p)
  • sed irade çıktı hatları yazdırmadan önce (normal ifadede \(...\) arasında ne karşılık gelen \1) köşeli parantez arasında ne tutmak
  • awk, alan sınırlayıcıları olarak 0 veya daha fazla boşlukla çevrili bir virgül (-F ' *, *') kullanır; $1, ilk sütuna (ör. 8541), ikinci vb. Için $2'a karşılık gelir.kolonlar sonunda değeri 0
    • sayılır Eksik, awk, işlenmiş kayıtların sayısına göre akümülatörler sum2 vb böler NR
  • gawk yapar Tek atışta her şey; ilk olarak, her satırın önceki örnekte geçirilen aynı düzenli ifadenin sed ile eşleşip eşleşmeyeceğini (sed, awk'dan farklı olarak \'un fron içinde alanları veya ilgiyi sınırlayan yuvarlak köşeli ayraçlar gerektirmediğini) test edecektir. Çizgi eşleşirse, yuvarlak köşeli parantezlerin arasında [1] 'de biter, daha sonra aynı ayırıcıyı (herhangi bir sayıdaki boşlukla çevrili bir virgül) ayırır ve biriktirmek için kullanırız. Bunun yerine NR işlenen kayıt sayısı tüm hatlar garanti sed beri sed|awk durumda değildi formu INFO ... [...comma-separated-numbers...] ait olup olmadığını ilgili kayıtların sayısını (cnt) daha büyük olabilir, çünkü NR kullanmaya devam etme cnt tanıtıldı awk'a iletilen tüm satırlar alakalıydı.
+0

Harika! Açıklamalar için teşekkürler! –

0

Kullanım nawk veya /usr/xpg4/bin/awkSolaris.

awk -F'[],]' 'END { 
    print s/NR, t/ct 
    } 
{ 
    s += $(NF-3) 
    if ($(NF-1)) { 
    t += $(NF-2) 
    ct++ 
    } 
    }' infile 
0

Kullanım Python

logfile= open("somelogfile.log", "r") 
sum2, count2= 0, 0 
sum3, count3= 0, 0 
for line in logfile: 
    # find right-most brackets 
    _, bracket, fieldtext = line.rpartition('[') 
    datatext, bracket, _ = fieldtext.partition(']') 
    # split fields and convert to integers 
    data = map(int, datatext.split(',')) 
    # compute sums and counts 
    sum2 += data[1] 
    count2 += 1 
    if data[3] != 0: 
     sum3 += data[2] 
     count3 += 1 
logfile.close() 

print sum2, count2, float(sum2)/count2 
print sum3, count3, float(sum3)/count3 
İlgili konular