로그 파일을 통해 계산을 수행하는 방법
문제
나는 다음과 같이 보인다 :
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
- SED는 다음과 같은 선을 출력합니다.
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