문제

나는 다음과 같이 보인다 :

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]

괄호 안의 2 차 및 세 번째 필드의 평균을 계산하는 쉘 스크립트를 만들고 싶습니다.840 그리고 0 마지막 예에서). 더 강력한 질문 : 마지막 필드가 아닌 경우에만 3 번째 필드의 평균을 얻을 수 있습니까? 0?

나는 내가 사용할 수 있다는 것을 안다 Ruby 또는 스크립트를 만들 수있는 다른 언어이지만 Bash. 그러한 스크립트를 만드는 방법에 대한 자원이나 힌트에 대한 좋은 제안이 도움이 될 것입니다.

도움이 되었습니까?

해결책

답장을 게시하면서 여기에 당신에게 붙여 넣은 것도 여기에 있습니다.

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

다른 팁

사용 bash 그리고 awk:

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 }'

샘플 출력 (원래 데이터의 경우) :

avg2=2859.59, avg3=149.94

물론, 당신은 사용할 필요가 없습니다 cat, 그것은 가독성을 위해 포함되며 입력 데이터가 모든 파이프에서 나올 수 있다는 사실을 설명합니다. 기존 파일에서 작동 해야하는 경우 실행하십시오. sed -ne '...' file | ... 곧장.


편집하다

액세스 할 수있는 경우 gawk (gnu awk), 당신은 sed 다음과 같이 :

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 }'

같은 발언 re. cat 적용하다.

약간의 설명 :

  • sed 라인 만 인쇄합니다 (-n ... :p 조합)는 정규 표현식 (라인 끝에있는 정사각형 브래킷 사이의 숫자, 공백 및 쉼표를 포함하는 라인)과 일치하는 조합; 그러한 라인이 일치하는 경우 사각형 브래킷 사이에만 유지하십시오 (\1, 사이의 것에 해당합니다 \(...\) 인쇄하기 전 (정규 표현)에서 (:p)
    • SED는 다음과 같은 선을 출력합니다. 8541, 931, 0, 0
  • awk 0 개 이상의 공간으로 둘러싸인 쉼표를 사용합니다 (-F ' *, *') 현장 구분자로서; $1 첫 번째 열 (예 : 8541)에 해당합니다. $2 두 번째 등. 누락 된 열은 값으로 간주됩니다 0
    • 결국, awk 축적기를 나눕니다 sum2 처리 된 레코드 수에 의해 등, NR
  • gawk 한 번에 모든 것을 수행합니다. 먼저 각 라인이 이전 예에서 전달 된 동일한 정규 표현과 일치하는지 테스트합니다. sed (그와 달리 sed, awk 필요하지 않습니다 \ 둥근 괄호가 영역을 구하고 관심을 끄는 괄호). 라인이 일치하면 둥근 괄호 사이의 것은 [1]으로 끝나고 동일한 분리기 (수많은 공간으로 둘러싸인 쉼표)를 사용하여 분할하고 그것을 사용합니다. 나는 소개했다 cnt 계속 사용하는 대신 NR 레코드 수가 처리 되었기 때문입니다 NR 실제 관련 레코드 수보다 클 수 있습니다 (cnt) 모든 라인이 양식 인 경우 INFO ... [...comma-separated-numbers...], 그것은 사실이 아니었다 sed|awk ~부터 sed 모든 라인이 전달되도록 보장했습니다 awk 관련이있었습니다.

사용 nawk 또는 /usr/xpg4/bin/awk ~에 Solaris.

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

파이썬을 사용하십시오

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
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top