Unix Shell:汇总值,每行一个但跳过每第n行

时间:2013-10-28 23:16:21

标签: shell unix scripting

我正在尝试设计一个Unix shell脚本(最好是通用的sh),它将获取一个内容为数字的文件,每行一个。这些数字是从mpstat获得的CPU空闲时间:

cat ${PARSE_FILE} | awk '{print $13}' | grep "^[!0-9]" > temp.txt

因此,如果是数字,文件就是一个列表,如:

46.19
93.41
73.60
99.40
95.80
96.00
77.10
99.20
52.76
81.18
69.38
89.80
97.00
97.40
76.18
97.10

这些值的真正含义是第1行是Core 1,第2行是Core 2,等等......对于X个核心(在我的例子中是8) - 所以每第9行再次为Core 1等...

原始文件如下所示:

10/28/2013  Linux 2.6.32-358.el6.x86_64 (host)  10/28/2013  _x86_64_    

(32 CPU)
10/28/2013  
10/28/2013  02:25:05 PM  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest   %idle
10/28/2013  02:25:15 PM    0   51.20    0.00    2.61    0.00    0.00    0.00    0.00    0.00   46.19
10/28/2013  02:25:15 PM    1    6.09    0.00    0.50    0.00    0.00    0.00    0.00    0.00   93.41
10/28/2013  02:25:15 PM    2   25.20    0.00    1.20    0.00    0.00    0.00    0.00    0.00   73.60
10/28/2013  02:25:15 PM    3    0.40    0.00    0.20    0.00    0.00    0.00    0.00    0.00   99.40
10/28/2013  02:25:15 PM    4    3.80    0.00    0.40    0.00    0.00    0.00    0.00    0.00   95.80
10/28/2013  02:25:15 PM    5    3.70    0.00    0.30    0.00    0.00    0.00    0.00    0.00   96.00
10/28/2013  02:25:15 PM    6   21.70    0.00    1.20    0.00    0.00    0.00    0.00    0.00   77.10
10/28/2013  02:25:15 PM    7    0.70    0.00    0.10    0.00    0.00    0.00    0.00    0.00   99.20
10/28/2013  02:25:25 PM    0   45.03    0.00    1.61    0.00    0.00    0.60    0.00    0.00   52.76
10/28/2013  02:25:25 PM    1   17.82    0.00    1.00    0.00    0.00    0.00    0.00    0.00   81.18
10/28/2013  02:25:25 PM    2   29.62    0.00    1.00    0.00    0.00    0.00    0.00    0.00   69.38
10/28/2013  02:25:25 PM    3    9.70    0.00    0.40    0.00    0.00    0.10    0.00    0.00   89.80
10/28/2013  02:25:25 PM    4    2.40    0.00    0.60    0.00    0.00    0.00    0.00    0.00   97.00
10/28/2013  02:25:25 PM    5    2.00    0.00    0.60    0.00    0.00    0.00    0.00    0.00   97.40
10/28/2013  02:25:25 PM    6   22.92    0.00    0.90    0.00    0.00    0.00    0.00    0.00   76.18
10/28/2013  02:25:25 PM    7    2.40    0.00    0.50    0.00    0.00    0.00    0.00    0.00   97.10

我正在尝试设计一个脚本,它将核心数量和此文件作为变量,并获得每个核心的平均值,我不知道如何做到这一点。这就是我所拥有的:

cat ${PARSE_FILE} | awk '{print $13}' | grep "^[!0-9]" > temp.txt
NUMBER_OF_CORES=8
NUMBER_OF_LINES=`awk ' END { print NR } ' temp.txt`
NUMBER_OF_VALUES=`echo "scale=0;${NUMBER_OF_LINES}/${NUMBER_OF_CORES}" | bc`
for i in `seq 1 ${NUMBER_OF_CORES}`
do
  awk 'NR % $i == 0' temp.txt
  echo Core: ${i} Average: xx
done

所以我有每个核心所拥有的值(核心线数),所以这是我需要跳过的第n行,但我不确定如何干净地执行此操作。我基本上需要在文件中循环每次“NUMBER_OF_CORES”次,跳过每个“NUMBER_OF_CORES”行并将它们相加以除以“NUMBER_OF_VALUES”。

4 个答案:

答案 0 :(得分:1)

countCores.sh下面的脚本基于您在temp.txt中提供的数据 这可能不是你想要的,但会给你一些想法。我不确定 您想要的总体平均值,所以我只选择显示值的平均值 在第一列中,所有8个核心。我还用cat -n来表示核心编号。 希望这可以帮助。 VonBell

#!/bin/bash
#Execute As: countCores.sh temp.txt 8
AllCoreTotals=0
DataFile="$1"
NumCores="$2"
AllCoreTotals=0
NumLines="`cat -n $DataFile|cut -f1|tail -1|tr -d " "`"
PrtCols="`echo $NumLines / $NumCores|bc`"
clear;echo;echo
echo "============================================================="
pr -t${PrtCols} $DataFile|tr -d "\t"|tr -s " "  "+"|bc |\
while read CoreTotal
    do
       CoreAverage=`echo $CoreTotal / $PrtCols|bc`
       echo "$CoreTotal     Core Average $CoreAverage"
       AllCoreTotals="`echo $CoreTotal + $AllCoreTotals|bc`"
       echo "$AllCoreTotals"  > AllCoreTot.tmp
    done|cat -n
AllCoreAverage=`cat AllCoreTot.tmp`
AllCoreAverage="`echo $AllCoreAverage / $NumCores|bc`"
echo "============================================================="
echo "(Col One) Total Core Average: $AllCoreAverage "
rm $DataFile
rm AllCoreTot.tmp

答案 1 :(得分:1)

为什么不同时为所有核心做这件事:

awk -f prog.awk ${PARSE_FILE}

然后在prog.awk put

    {   if ((NF == 13) && ($4 != "CPU"))
        {   SUM[$4] += $13;
            CNT[$4]++;
        }
    }
END {   for(loop in SUM)
        {   printf("CPU: %d  Total: %d  Count: %d  Average: %d\n",
                    loop, SUM[loop], CNT[loop], SUM[loop]/CNT[loop]);
        }
    }

如果你想在一行上这样做:

awk '{if ((NF == 13) && ($4 != "CPU")){SUM[$4] += $13;CNT[$4]++;}} END {for(loop in SUM){printf("CPU: %d  Total: %d  Count: %d  Average: %d\n", loop, SUM[loop], CNT[loop], SUM[loop]/CNT[loop]);}}'  ${PARSE_FILE}

答案 2 :(得分:1)

这会吗?

awk '/CPU/&&/idle/{f=1;next}f{a[$4]+=$13;b[$4]++}END{for(i in a){print i,a[i]/b[i]}}' your_file

实际上这里不需要核心数量。它将计算文件中所有可用内核的平均空闲时间

测试:

> cat temp
10/28/2013  Linux 2.6.32-358.el6.x86_64 (host)  10/28/2013  _x86_64_    

(32 CPU)
10/28/2013  
10/28/2013  02:25:05 PM  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest   %idle
10/28/2013  02:25:15 PM    0   51.20    0.00    2.61    0.00    0.00    0.00    0.00    0.00   46.19
10/28/2013  02:25:15 PM    1    6.09    0.00    0.50    0.00    0.00    0.00    0.00    0.00   93.41
10/28/2013  02:25:15 PM    2   25.20    0.00    1.20    0.00    0.00    0.00    0.00    0.00   73.60
10/28/2013  02:25:15 PM    3    0.40    0.00    0.20    0.00    0.00    0.00    0.00    0.00   99.40
10/28/2013  02:25:15 PM    4    3.80    0.00    0.40    0.00    0.00    0.00    0.00    0.00   95.80
10/28/2013  02:25:15 PM    5    3.70    0.00    0.30    0.00    0.00    0.00    0.00    0.00   96.00
10/28/2013  02:25:15 PM    6   21.70    0.00    1.20    0.00    0.00    0.00    0.00    0.00   77.10
10/28/2013  02:25:15 PM    7    0.70    0.00    0.10    0.00    0.00    0.00    0.00    0.00   99.20
10/28/2013  02:25:25 PM    0   45.03    0.00    1.61    0.00    0.00    0.60    0.00    0.00   52.76
10/28/2013  02:25:25 PM    1   17.82    0.00    1.00    0.00    0.00    0.00    0.00    0.00   81.18
10/28/2013  02:25:25 PM    2   29.62    0.00    1.00    0.00    0.00    0.00    0.00    0.00   69.38
10/28/2013  02:25:25 PM    3    9.70    0.00    0.40    0.00    0.00    0.10    0.00    0.00   89.80
10/28/2013  02:25:25 PM    4    2.40    0.00    0.60    0.00    0.00    0.00    0.00    0.00   97.00
10/28/2013  02:25:25 PM    5    2.00    0.00    0.60    0.00    0.00    0.00    0.00    0.00   97.40
10/28/2013  02:25:25 PM    6   22.92    0.00    0.90    0.00    0.00    0.00    0.00    0.00   76.18
10/28/2013  02:25:25 PM    7    2.40    0.00    0.50    0.00    0.00    0.00    0.00    0.00   97.10
> nawk '/CPU/&&/idle/{f=1;next}f{a[$4]+=$13;b[$4]++}END{for(i in a){print i,a[i]/b[i]}}' temp
2 71.49
3 94.6
4 96.4
5 96.7
6 76.64
7 98.15
0 49.475
1 87.295
> 

答案 3 :(得分:0)

经过一番研究后,这个片段似乎可以解决问题:

#Parse logs to get CPU averages for cores
PARSE_FILE=`ls ~/logs/*mpstat*`
echo "Parsing ${PARSE_FILE}..."
cat ${PARSE_FILE} | awk '{print $13}' | grep "^[!0-9]" > temp.txt
NUMBER_OF_CORES=8
NUMBER_OF_LINES=`awk ' END { print NR } ' temp.txt`
NUMBER_OF_VALUES=`echo "scale=0;${NUMBER_OF_LINES}/${NUMBER_OF_CORES}" | bc`
TOTAL=0
for i in `seq 1 ${NUMBER_OF_CORES}`
do
  sed -n $i'~'$NUMBER_OF_CORES'p' temp.txt > temp2.txt
  SUM=`awk '{s+=$0} END {print s}' temp2.txt`
  AVERAGE=`echo "scale=0;${SUM}/${NUMBER_OF_VALUES}" | bc`
  echo Core: ${i} Average: `expr 100 - ${AVERAGE}`
  TOTAL=$((TOTAL+${AVERAGE}))
done
TOTAL_AVERAGE=`echo "scale=0;${TOTAL}/${NUMBER_OF_CORES}" | bc`
echo "Total Average: `expr 100 - ${TOTAL_AVERAGE}`"
rm temp*.txt