shell脚本练习题答案

Q1答案

  1. awk '{url[$7]++;size[$7]+=$10}END{for (a in url) {print size[a]/1024"K",url[a],a}}' access.log

解析:
这里定义了两个数组url和size,数组url用来计算单个url被访问的次数,数组size则是统计单个url传输的总字节数。之后的for语句则是循环读取数组url的无素,即链接,然后相继打印出单个url传输总字节数,被访问次数及相应的链接。
数据分析出来后,我们可以使用sort命令进行排序。

Q2答案

方法1:for…do…done 的数值处理

  1. sum=0
  2. for ((i=1;i<=100;i++))
  3. do
  4. ((sum+=$i))
  5. done

方法2:for…do…done (固定回圈)

  1. sum=0
  2. for i in {1..100}
  3. do
  4. ((sum+=$i))
  5. done

方法3:while do done (不定回圈)

  1. sum=0
  2. i=1
  3. while [[ $i -le 100 ]]
  4. do
  5. ((sum+=i))
  6. ((i++))
  7. done

方法4:until do done (不定回圈)

  1. sum=0
  2. i=1
  3. until [[ $i -gt 100 ]]
  4. do
  5. ((sum+=i))
  6. ((i++))
  7. done

方法5:构建1+2+3..再利用bc计算

  1. seq 100 | tr "\n" "+" | sed 's/+$/\n/' | bc

Q3答案

  1. now=`date +%H%M%S`
  2. ago=`date -d "1 minute ago" +%H%M%S`
  3. badip=`tail -n 10000 access.log | egrep -v "\.(gif|jpg|jpeg|png|css|js)" | awk  '
  4. BEGIN{
  5. n='"$now"'
  6. a='"$ago"'
  7. FS="[ :]+"
  8. }
  9. {
  10. t=$5$6$7
  11. if (t>=a && t<=n) {
  12. num[$1]++
  13. }
  14. }
  15. END{
  16. for (ip in num){
  17. if (num[ip]>60){
  18. print ip
  19. }
  20. }
  21. }
  22. '`
  23. if [ ! -z "$badip" ];then
  24. for ip in $badip;
  25. do
  26. if test -z "`/sbin/iptables -nL | grep $ip`";then
  27. /sbin/iptables -I INPUT -s $ip -j DROP
  28. fi
  29. done
  30. fi

解析:
1、定义两个变量now和ago,分别为当前时间,一分钟前的时间,格式为%H%M%S。
2、获取日志最后的一万行(可以根据自己的访问量修改),使用egrep排除图片等文件。
3、在awk的BEGIN语句中调用第1步设置的两个变量。
4、使用变量t,a,n判断并获取一分钟内的日志,并使用数组num统计ip出现的次数。
5、在END语句中判断ip出现的次数是否超过60,如果超过则输出ip地址到变量badip。
6、for循环获取变量badip中的每个ip,并加入iptables规则禁止访问。

Q4答案

  1. awk -F, 'BEGIN{
  2. printf "%-10s %s\n","Name","Average"
  3. printf "%-10s %s\n","----","-------"
  4. }
  5. NR>1{
  6. sum=0
  7. n=0
  8. for (i=3;i<=5;i++){
  9. if ($i>0){
  10. n++
  11. sum=sum+$i
  12. testcount[i-2]++
  13. testtotal[i-2]+=$i
  14. teamcount[$2]++
  15. teamtotal[$2]+=$i
  16. }
  17. }
  18. printf "%-10s %7.2f\n",$1,sum/n
  19. }
  20. END{
  21. print "------------------"
  22. for (j=1;j<=3;j++){
  23. print "Average for Test "j" : "testtotal[j]/testcount[j]
  24. }
  25. print "-------------------"
  26. for (t in teamcount){
  27. print "Average for "t" Team: "teamtotal[t]/teamcount[t]
  28. }
  29. }'  teamlist.txt

解析:
1、awk的BEGIN语句输出表的两个列名。
2、NR>1表示只处理从第二行开始的数据
3、sum=0,n=0,初始化三个测试总成绩和参加的次数。
4、定义一个for循环,循环处理三次测试数据。
5、判断成绩大于0才处理此次测试。
6、为计算每个人的平均成绩,用变量n记录测试次数,变量sum累积三次的成绩,接着下面用printf格式化输出每个人的平均成绩;为计算三个测试中每次的平均成绩,以i-2作为索引(即第i-2次测试),数组testcount记录某次测试参加的人数,数组testtotal记录某次测试的总成绩;为计算每个组的平均成绩,以第二列组名作为索引,数组teamcount记录某组参加测试的人数,数组teamtotal记录某组的总成绩。
7、在END语句中用两个for循环语句分别输出每次测试及每组测试的平均成绩。

Q5答案

方法一:利用awk命令计算

  1. if [ "$#" -lt 2 ];then
  2. echo "parameter must be at least 3."
  3. exit 1
  4. fi
  5. echo "$@" | awk '
  6. BEGIN{
  7. RS=" +"
  8. }
  9. {
  10. sum+=$0
  11. }
  12. NR==1 {
  13. max=$1;min=$1
  14. next
  15. }
  16. $1>max {
  17. max=$1
  18. }
  19. $1<min {
  20. min=$1
  21. }
  22. END{
  23. printf "max number is:%s\n",max
  24. printf "min number is:%s\n",min
  25. printf "average is:%.2f\n",sum/NR
  26. }'

解析:
1、判断参数是否大于2个,否则退出脚本。
2、管道传入所有参数到awk,并设置awk的RS为空格。
3、sum+=$0,计算和。
4、NR==1 {}把第一个参数先赋值到max和min,防止所有数字为负数时计算错误。
5、$1>max{}判断数字是否比变量max目前的数大,如果是,则把$1赋值到max,这样变量就可以时刻保持最大值状态。
6、$1

  1. n=$#
  2. if [ "$n" -lt 2 ];then
  3. echo "parameter must be at least 3."
  4. exit 1
  5. fi
  6. max=$1
  7. min=$1
  8. sum=$1
  9. shift
  10. while [ $# -gt 0 ]
  11. do
  12. ((sum+=$1))
  13. [ $1 -gt $max ] && max=$1
  14. [ $1 -lt $min ] && min=$1
  15. shift
  16. done
  17. echo "max number is:"$max
  18. echo "min number is:"$min
  19. ave=`echo "scale=2;$sum / $n" | bc`
  20. echo "average is:"$ave

标签:Shell 发布于:2019-11-23 07:15:28