2014-01-06 2 views
0

Это скрипт, который я запускаю выводить исходные данные data_tripwire.shКак разбить вход на куски по шесть записей, используя bash?

#!/bin/sh 

    LOG=/var/log/syslog-ng/svrs/sec2tes1 

for count in 6 5 4 3 2 1 0 
do 
    MONTH=`date -d"$count month ago" +"%Y-%m"` 

    CBS=`bzcat $LOG/$MONTH*.log.bz2|grep 10.55.22.41 |sort|uniq | wc -l` 
    echo $CBS >> /home/secmgr/attmrms1/data_tripwire1.sh 
done 

for count in 6 5 4 3 2 1 0 
do 
    MONTH=`date -d"$count month ago" +"%Y-%m"` 

    GFS=`bzcat $LOG/$MONTH*.log.bz2|grep 10.55.22.31 |sort|uniq | wc -l` 
    echo $GFS >> /home/secmgr/attmrms1/data_tripwire1.sh 
done 

for count in 6 5 4 3 2 1 0 
do 
    MONTH=`date -d"$count month ago" +"%Y-%m"` 

    HR1=`bzcat $LOG/$MONTH*.log.bz2|grep 10.55.10.1 |sort|uniq | wc -l ` 
    echo $HR1 >> /home/secmgr/attmrms1/data_tripwire1.sh 
done 


for count in 6 5 4 3 2 1 0 
do 
    MONTH=`date -d"$count month ago" +"%Y-%m"` 

    HR2=`bzcat $LOG/$MONTH*.log.bz2|grep 10.55.21.12 |sort|uniq | wc -l` 
    echo $HR2 >> /home/secmgr/attmrms1/data_tripwire1.sh 
done 

for count in 6 5 4 3 2 1 0 
do 
    MONTH=`date -d"$count month ago" +"%Y-%m"` 

    PAYROLL=`bzcat $LOG/$MONTH*.log.bz2|grep 10.55.21.18 |sort|uniq | wc -l` 
    echo $PAYROLL >> /home/secmgr/attmrms1/data_tripwire1.sh 

done 

for count in 6 5 4 3 2 1 0 
do 
    MONTH=`date -d"$count month ago" +"%Y-%m"` 

    INCV=`bzcat $LOG/$MONTH*.log.bz2|grep 10.55.22.71 |sort|uniq | wc -l` 
    echo $INCV >> /home/secmgr/attmrms1/data_tripwire1.sh 
done 

data_tripwire.sh

91 
58 
54 
108 
52 
18 
8 
81 
103 
110 
129 
137 
84 
15 
14 
18 
11 
17 
12 
6 
1 
28 
6 
14 
8 
8 
0 
0 
28 
24 
25 
23 
21 
13 
9 
4 
18 
17 
18 
30 
13 
3 

Я хочу сделать первые 6 записей (91,58,54,108, 52,18) из вышесказанного. Затем он вырвется из цикла. После этого он будет продолжаться для следующих 6 записей. Затем он снова выйдет из цикла ....

Проблема в том, что она считывает все 42 номера без нарушения вне цикла.

Это выход из таблицы

Tripwire 

Month CBS  GFS  HR  HR   Payroll INCV 
     cb2db1 gfs2db1 hr2web1 hrm2db1 hrm2db1a incv2svr1 
2013-07 85  76  12  28  26   4 
2013-08 58  103  18  6   24   18 
2013-09 54  110  11  14  25   17 
2013-10 108  129  17  8   23   18 
2013-11 52  137  12  8   21   30 
2013-12 18  84  6  0   13   13 
2014-01 8  16  1  0   9   3 

Сейчас проблема заключается в том, что он считывал всего 42 номеров из 85 ... 3 Я хочу сделать цикл, который запускается из июля до января для одного server.Then он будет делать средний средний и стандартный расчет отклонения, который уже сделан ниже. После этого он продолжит следующий цикл из 6 чисел для следующего сервера, и он будет делать то же самое, что и начальный цикл. Сопротивление требуется для циклов for, которые имеют разрыв и продолжают в нем или все проще.

Это мой стандартный расчет отклонения

count=0   # Number of data points; global. 
SC=3   # Scale to be used by bc. three decimal places. 
E_DATAFILE=90 # Data file error 

## ----------------- Set data file --------------------- 

if [ ! -z "$1" ] # Specify filename as cmd-line arg? 
then 
    datafile="$1" # ASCII text file, 
else   #+ one (numerical) data point per line! 
    datafile=/home/secmgr/attmrms1/data_tripwire1.sh 
fi    # See example data file, below. 

if [ ! -e "$datafile" ] 
then 
    echo "\""$datafile"\" does not exist!" 
    exit $E_DATAFILE 
fi 

Подсчитать среднее

arith_mean() 
{ 
    local rt=0   # Running total. 
    local am=0   # Arithmetic mean. 
    local ct=0   # Number of data points. 

    while read value # Read one data point at a time. 
    do 
    rt=$(echo "scale=$SC; $rt + $value" | bc) 
    ((ct++)) 
    done 

    am=$(echo "scale=$SC; $rt/$ct" | bc) 

    echo $am; return $ct # This function "returns" TWO values! 
    # Caution: This little trick will not work if $ct > 255! 
    # To handle a larger number of data points, 
    #+ simply comment out the "return $ct" above. 
} <"$datafile" # Feed in data file. 

sd() 
{ 
    mean1=$1 # Arithmetic mean (passed to function). 
    n=$2  # How many data points. 
    sum2=0 # Sum of squared differences ("variance"). 
    avg2=0 # Average of $sum2. 

sdev=0 # Standard Deviation. 

    while read value # Read one line at a time. 
    do 
    diff=$(echo "scale=$SC; $mean1 - $value" | bc) 
    # Difference between arith. mean and data point. 
    dif2=$(echo "scale=$SC; $diff * $diff" | bc) # Squared. 
    sum2=$(echo "scale=$SC; $sum2 + $dif2" | bc) # Sum of squares. 
    done 

    avg2=$(echo "scale=$SC; $sum2/$n" | bc) # Avg. of sum of squares. 
    sdev=$(echo "scale=$SC; sqrt($avg2)" | bc) # Square root = 
    echo $sdev         # Standard Deviation. 

} <"$datafile" # Rewinds data file. 

Отображение выходного

mean=$(arith_mean); count=$? # Two returns from function! 
std_dev=$(sd $mean $count) 

echo 
echo "<tr><th>Servers</th><th>"Number of data points in \"$datafile"\"</th> <th>Arithmetic mean (average)</th><th>Standard Deviation</th></tr>" >> $HTML 
echo "<tr><td>cb2db1<td>$count<td>$mean<td>$std_dev</tr>" >> $HTML 
echo "<tr><td>gfs2db1<td>$count<td>$mean<td>$std_dev</tr>" >> $HTML 
echo "<tr><td>hr2web1<td>$count<td>$mean<td>$std_dev</tr>" >> $HTML 
echo "<tr><td>hrm2db1<td>$count<td>$mean<td>$std_dev</tr>" >> $HTML 
echo "<tr><td>hrm2db1a<td>$count<td>$mean<td>$std_dev</tr>" >> $HTML 
echo "<tr><td>incv21svr1<td>$count<td>$mean<td>$std_dev</tr>" >> $HTML 

echo 

Я хочу, чтобы разделить вход на куски шесть записей каждый с среднее арифметическое и sd записей 1..6, то из записей 7..12, то из 13..18 и т. Д.

Это результат таблицы, которую я хочу.

Tripwire 

Month CBS  GFS  HR  HR   Payroll INCV 
     cb2db1 gfs2db1 hr2web1 hrm2db1 hrm2db1a incv2svr1 
2013-07 85  76  12  28  26   4 
2013-08 58  103  18  6   24   18 
2013-09 54  110  11  14  25   17 
2013-10 108  129  17  8   23   18 
2013-11 52  137  12  8   21   30 
2013-12 18  84  6  0   13   13 
2014-01 8  16  1  0   9   3 
*Standard 
deviation 
(7mths) 31.172 35.559 5.248 8.935 5.799 8.580 
* Mean 
(7mths) 54.428 94.285 11.142 9.142 20.285 14.714 
+0

Действительно ли работает переназначение вне определения функции, а не в цикле 'while read' внутри функции? – Barmar

+0

Прочитайте ввод вне функций и поместите его в массив. После каждых 6 строк вызовите свои функции с массивом в качестве аргумента. Затем очистите массив и продолжите цикл. – Barmar

+0

Вы пытаетесь разделить свой вход на куски по шесть записей? Итак, вы хотите получить среднее арифметическое и sd записей 1..6, затем записей 7..12, затем 13,18 и т. Д.? – Alfe

ответ

2
paste - - - - - - < data_tripwire.sh | while read -a values; do 
    # values is an array with 6 values 
    # ${values[0]} .. ${values[5]} 
    arith_mean "${values[@]}" 
done 

Это означает, что вы должны переписать функцию так, что они не используют read: изменение

while read value 

в

for value in "[email protected]" 

@ Matt, да изменения обе функции выполняют итерацию по аргументам вместо r еде из stdin. Затем вы передадите файл данных (теперь называемый «data_tripwire1.sh» (ужасное расширение файла для данных, используйте .txt или .dat)) в paste, чтобы переформатировать данные так, чтобы первые 6 значений теперь составляли первую строку. Прочитайте строку в массив values (используя read -a values) и вызывать функции:

arith_mean() { 
    local sum=$(IFS=+; echo "$*") 
    echo "scale=$SC; ($sum)/$#" | bc 
} 
sd() { 
    local mean=$1 
    shift 
    local sum2=0 
    for i in "[email protected]"; do 
     sum2=$(echo "scale=$SC; $sum2 + ($mean-$i)^2" | bc) 
    done 
    echo "scale=$SC; sqrt($sum2/$#)"|bc 
} 

paste - - - - - - < data_tripwire1.sh | while read -a values; do 
    mean=$(arith_mean "${values[@]}") 
    sd=$(sd $mean "${values[@]}") 
    echo "${values[@]} $mean $sd" 
done | column -t 
91 58 54 108 52 18 63.500 29.038 
8 81 103 110 129 137 94.666 42.765 
84 15 14 18 11 17 26.500 25.811 
12 6 1 28 6 14 11.166 8.648 
8 8 0 0 28 24 11.333 10.934 
25 23 21 13 9 4 15.833 7.711 
18 17 18 30 13 3 16.500 7.973 

Примечание Вам не нужно возвращать фантазии значение из функций: вы знаете, сколько очков вы передаете в.

+0

Где я вставляю цикл while? я должен переписать как среднюю, так и стандартную функцию отклонения? – Matt

+0

где я объявляю значения для массивов – Matt

+0

Я предполагаю, что это должно быть 'data_tripwire.sh | паста - - - - - - | при чтении значений -a; do' ... – Alfe

0

Теперь функции смогут читать только 6 элементов в файле данных.

arith_mean() 
{ 
    local rt=0   # Running total. 
    local am=0   # Arithmetic mean. 
    local ct=0   # Number of data points. 

    while read value # Read one data point at a time. 
    do 
    rt=$(echo "scale=$SC; $rt + $value" | bc) 
    ((ct++)) 
    done 

    am=$(echo "scale=$SC; $rt/$ct" | bc) 

    echo $am; return $ct # This function "returns" TWO values! 
    # Caution: This little trick will not work if $ct > 255! 
    # To handle a larger number of data points, 
    #+ simply comment out the "return $ct" above. 
} <(awk -v block=$i 'NR > (6* (block - 1)) && NR < (6 * block + 1) {print}' "$datafile") # Feed in data file. 

sd() 
{ 
    mean1=$1 # Arithmetic mean (passed to function). 
    n=$2  # How many data points. 
    sum2=0 # Sum of squared differences ("variance"). 
    avg2=0 # Average of $sum2. 

sdev=0 # Standard Deviation. 

    while read value # Read one line at a time. 
    do 
    diff=$(echo "scale=$SC; $mean1 - $value" | bc) 
    # Difference between arith. mean and data point. 
    dif2=$(echo "scale=$SC; $diff * $diff" | bc) # Squared. 
    sum2=$(echo "scale=$SC; $sum2 + $dif2" | bc) # Sum of squares. 
    done 

    avg2=$(echo "scale=$SC; $sum2/$n" | bc) # Avg. of sum of squares. 
    sdev=$(echo "scale=$SC; sqrt($avg2)" | bc) # Square root = 
    echo $sdev         # Standard Deviation. 

} <(awk -v block=$i 'NR > (6 * (block - 1)) && NR < (6 * block + 1) {print}' "$datafile") # Rewinds data file. 

Оттуда вам нужно будет установить блоки для чтения.

for((i=1; i <= $(($(wc -l $datafile | sed 's/[A-Za-z \/]*//g')/6)); i++)) 
do 
    mean=$(arith_mean); count=$? # Two returns from function! 
    std_dev=$(sd $mean $count) 
done 

Конечно, лучше, чтобы переместить wc -l вне петли для более быстрого выполнения. Но ты получил идею.

Ошибка синтаксиса между < и ( из-за пробела. Между ними не должно быть места. Извините за опечатку.

cat <(awk -F: '{print $1}' /etc/passwd) работает.

cat < (awk -F: '{print $1}' /etc/passwd) ошибка синтаксиса около неожиданной лексемы `(»

+0

Я хочу прочитать ввод по 6 записей каждый, после этого он сломает цикл, а затем продолжит читать следующие 6 .. – Matt

+0

Функция u написала только 6 пунктов, но не следующие 6 пунктов и последующие 6 .. – Matt

+0

./TripwireReview_Version3.sh: строка 110: синтаксическая ошибка около неожиданного токена '(' [secmgr @ sec2log1 attmrms1] $./TripwireReview_Version3.sh: строка 110:'} <(awk -v block = $ i' NR> (block-1) && NR <(6 * block + 1) {print} '"$ datafile") # Подача файла данных.' – Matt

0

На основании ответа Гленна я предлагаю это, который требует очень мало изменений в оригинал:

paste - - - - - - < data_tripwire.sh | while read -a values 
    do 
    for value in "${values[@]}" 
    do 
     echo "$value" 
    done | arith_mean 
    for value in "${values[@]}" 
    do 
     echo "$value" 
    done | sd 
    done 

Вы можете набрать (или скопировать & пасту), это код непосредственно в интерактивной оболочке.Это должно работать из коробки. Конечно, это невозможно, если вы собираетесь использовать это часто, поэтому вы можете поместить этот код в текстовый файл, сделать этот исполняемый файл и вызвать этот текст файл как сценарий оболочки. В этом случае вы должен добавить #!/bin/bash в качестве первой строки в этом файле.

Кредит Гленн Джекман за использование paste - - - - - -, который является реальным решением, которое я бы сказал.

+0

data_tripwire.sh состоит из необработанных данных из другого скрипта, который я запускаю. Прокрутите вверх. – Matt

+0

где я могу поместить предложенный код в сценарии? – Matt

+0

Очень необычно назвать файл, содержащий вывод другого вызова, например, '* .sh'. Обычно такие имена (то есть этот суффикс) используются для сценариев оболочки, которые являются _programs_, а не данными. Но в любом случае, если этот файл не генерирует _генерацию данных при вызове, а _ содержит данные, тогда мне придется отрегулируйте мое решение. Что касается вашего вопроса, где поставить этот код, я уточню это в ответе. Поэтому, пожалуйста, см. Мой обновленный ответ. – Alfe

Смежные вопросы