В ударе я могу grep измерения некоторого времени от файла журнала как это
grep "time:" myLogfile.txt | cut -d' ' -f 3 >> timeMeasurements.txt
#timeMeasurements.txt
2.5
3.5
2.0
...
Теперь я хотел бы вычислить среднее значение из значений в timeMeasurements.txt
. Что самый быстрый путь состоит в том, чтобы сделать это в ударе?
Я знаю, что существует gnuplot и R, но кажется, что нужно записать некоторый длинный сценарий для любого на них.
Иначе, с помощью sed
и bc
:
sed 's/^/n+=1;x+=/;$ascale=1;x/n' timemeasurements.txt | bc
sed выражение преобразовывает вход во что-то вроде этого:
n+=1;x+=2.5
n+=1;x+=3.5
n+=1;x+=2.0
scale=1;x/n
Это передается по каналу к bc
, который оценивает его линию за линией.
Вы могли использовать awk
. Сам Bash не очень хорош в математике...
awk 'BEGIN { lines=0; total=0 } { lines++; total+=$1 } END { print total/lines }' timeMeasurements.txt
lines=0; total=0
переменные набора к 0 lines++
увеличение lines
одним для каждой строки total+=$1
добавляет значение в каждой строке к рабочему общему количеству print total/lines
при выполнении разделите общее количество на количество значений Адаптация команды R от этот U& L сообщение :
$ Rscript -e 'd<-scan("stdin", quiet=TRUE)' -e 'cat(mean(d), sep="\n")' < foo
2.666667
datamash каждый кажется хорошим вариантом, но даже подтверждая, что мой ответ может быть излишеством, на всякий случай Вы хотите сделать немного больше, чем просто среднее, октава, не таким образом подробный:
$ octave
octave:1> load timeMeasurements.txt
octave:2> mean(timeMeasurements)
ans = 2.6667
при выполнении средств помните, что то же означает, мог прибыть из совсем других поведений, таким образом, стандартное отклонение обычно также релевантно:
octave:3> std(timeMeasurements)
ans = 0.76376
или даже простая гистограмма легко сделать:
octave:4> hist(timeMeasurements)
кроме того, я думаю, что datamash не находится в Кв. - получают репозитории для надежного человека, только для более новых версий.
Острота, для большего количества благоприятных для сценария использований:
octave -q --eval "m = load(\"timeMeasurements.txt\"); mean(m)"
Обязательный GNU datamash версия
$ datamash mean 1 < file
2.6666666666667
В СТОРОНЕ: такое чувство, что это действительно должно быть возможно исходно в bc
(т.е. не используя оболочку или внешнюю программу, для цикличного выполнения по входным значениям). GNU bc
реализация включает a read()
функция - однако это, кажется, разочаровывающе трудно заставить это обнаруживать конец входа. Лучшее, которое я мог придумать:
#!/usr/bin/bc
scale = 6
while( (x = read()) ) {
s += x
c += 1
}
s/c
quit
который можно затем передать вход файла по каналу к тому, если Вы завершаете вход с любым нечисловым символом, например.
$ { cat file; echo '@'; } | ./mean.bc
2.666666
Можно использовать bc
основной калькулятор, в a while
цикл с read
:
count=0; sum=0; while read -r num; do ((count++)); sum=$(echo "$sum + $num" | bc); done < timeMeasurement.txt; echo "scale=2; $sum / $count" | bc -l
Или больше четко:
count=0
sum=0
while read -r num
do
((count++))
sum=$(echo "$sum + $num" | bc)
done < timeMeasurement.txt
echo "scale=2; $sum / $count" | bc -l
Объяснение:
while read -r num; do ... ; done < timeMeasurements.txt
сделать это. Это будет означать, что мы сделаем что-то для каждой строки файла.((count++))
.$(...)
с echo
переданный по каналу к bc
добавить значение цифровой переменной для этой строки файла, к сумме цифровой переменной от всех предыдущих строк. bc
используется, поскольку удар не справляется хорошо с арифметикой с плавающей точкой.В этой точке концы цикла переменная количества содержит количество измерительных значений времени, переменная суммы содержит сумму измерений времени.
echo
с нашими переменными для создания среднего вычисления, которое передается bc
. scale=2
часть говорит bc
сколько значащих цифр для отображения.