명령을 여러 번 실행하여 제공된 여러 데이터 포인트의 평균을 조사하고 있습니다. 이 특별한 경우에는 sysbench
도구 키트를 사용하고 있습니다.
이 예제 입력은 단일 sysbench cpu <parameters>
실행에서 나온 것입니다. 일부 결과의 평균을 계산하기 위해 여러 번 실행된다는 점을 명심하세요.
CPU speed:
events per second: 827.81
General statistics:
total time: 30.0021s
total number of events: 44977
Latency (ms):
min: 2.01
avg: 4.93
max: 733.85
95th percentile: 12.98
sum: 228990.08
내 예제 스크립트에서
(for ((n=0;n<3;n++)); do
<command> | grep -i <data point lines>;
done) | awk '{ print $(NF) }'
각 실행에서 관련 데이터 포인트를 가져와 아래 각 줄의 마지막 필드를 (사용할 코드의 자리 표시자로) 인쇄합니다. 여기에는 내가 사용해야 하는 숫자가 포함되어 있습니다. 나에게 필요한 것은 모든 n $(NF) 를 더한 다음 평균을 내는 것인데, 이는 이미 개념화할 수 있습니다.
이 예에서 이러한 뷰를 취하고 싶다고 가정해 보겠습니다(현재는 grep을 통해 수행되지만 구현에는 신경 쓰지 않음).
events per second: 827.81
avg: 4.93
max: 733.85
95th percentile: 12.98
그리고 그것으로부터 마지막 열을 얻습니다 (현재 awk '{ print $(NF) }'를 통해)
827.81
4.93
733.85
12.98
기간당 출력 행이 4개이고 기간이 n개인 경우 동일한 필드와 일치하는 모든 행을 추가하고 싶습니다. 따라서 모든 avg:는 합산 및 평균화되며 max: 및 기타 통계에 대해서도 동일합니다.
add lines 1/5/9/4n
2/6/10/4n
3/7/11/4n
4/8/12/4n
together
awk를 사용하려고 합니다(이 코드는 여러 유닉스 시스템에서 사용되며 awk는 공통 요소이므로). 하지만 이 코드를 너무 복잡하게 만들고 더 나은 대안이 있다면 기꺼이 듣고 싶습니다. .
답변1
넌 뭔가를 얻을 수 있어폐쇄당신이 원하는 것에:
$ awk -F'[: ]' -v OFS=: '{sub("^ *","")};
/^(events|avg|min|95th)/ { sum[$1] += $NF ; count[$1]++ };
END { for (i in sum) print i, sum[i]/count[i] }' input.[123]
95th:11.3133
avg:4.53
events:691.143
min:2.31
참고: input.1, input.2 및 input.3은 값이 약간 편집된 예제 입력의 복사본입니다.
또한 참고: sub()
선행 공백을 제거하려면 스크립트의 첫 번째 줄에 사용하세요. $0이 변경되었으므로 필드 분할이 다시 평가되므로 $1에 사용 가능한(짧은) 이름이 있음이 보장됩니다. 우리는 그것이 무엇인지 별로 신경 쓰지 않고, 값을 추출하는 레코드 유형을 고유하게 식별한다는 점만 다릅니다.
불행하게도 연관 배열을 사용하기 때문에 출력 순서는 의사 무작위입니다(즉, 요소가 특정 순서로 나타날 것이라고 기대할 수 없습니다). 일관된 순서를 얻으려면 sort
첫 번째 출력 필드를 사용한 다음 cut
값을 얻으면 됩니다 .
$ awk -F'[: ]' -v OFS=: '{sub("^ *","")};
/^(events|avg|min|95th)/ { sum[$1] += $NF ; count[$1]++ };
END { for (i in sum) print i, sum[i]/count[i] }' input.[123] |
sort -t: -k1,1 | cut -d: -f2
11.3133
4.53
691.143
2.31
GNU awk가 있는 경우 이 asorti()
함수를 사용하여 연관 배열의 인덱스를 정렬할 수 있으므로 sort
및 cut
.
$ awk -F'[: ]' -v OFS=: '{sub("^ *","")};
/^(events|avg|min|95th)/ {sum[$1] += $NF ; count[$1]++ };
END {
num=asorti(sum,idx);
for (i=1;i<=num;i++) print sum[idx[i]]/count[idx[i]]
}' input.[123]
11.3133
4.53
691.143
2.31
답변2
다음과 같이 스크립트를 작성하세요.
{ for ((n=0; n<4; n++)); do <command>; done; } |\
awk -v t=$n 'i==t{ i=0 }
/(events per second|avg|max|95th percentile):/{ seen[++i]+=$NF/t }
END{ for(x in seen) print x, seen[x] }'