shell脚本基础知识(下)

七、shell中的case判断

格式: case  变量名 in

                      value1)

                           command

                           ;;

                      value2)

                           command

                           ;;

                       *)

                         commond

                             ;;

                esac


在case程序中,可以在条件中使用|,表示或的意思, 比如:    

2|3)

     command

     ;;

当变量为2或者3时,执行该部分命令。


应用举例:

[
root@hpf-linux
 shell]# cat test7.sh 
#!/bin/bash
read -p "请输入学生的成绩: " num
n1=`echo $num | sed 's/[0-9]//g'`         //判断是否为数字
if [ ! -z $n1 ]
then
    echo "这不是一个数字请从新输入!!"
exit 1 
fi
if  [[ $num -gt 100 || $num -lt 0 ]]
then
    echo  "学生的成绩为0-100,请从新输入!"
exit 1
elif [ $num -ge 90 ] && [ $num -le 100 ]
then 
    tag=1
elif [ $num -ge 80 ] && [ $num -le 90 ]
then
    tag=2
elif [ $num -ge 70 ] && [ $num -le 80 ]
then
    tag=3
elif [ $num -ge 60 ] && [ $num -le 70 ]
then
    tag=4
else 
    tag=5
fi
case $tag in
     1) 
echo "优秀!"
;;
     2) 
echo "良好!"
;;
     3)
echo "中等!"
;;
     4)
echo "万岁!及格啦!"
;;
     5)
echo "抱歉!你不及格!还需要补考!"
;;
esac
[
root@hpf-linux
 shell]# sh test7.sh 
请输入学生的成绩: 111
学生的成绩为0-100,请从新输入!
[
root@hpf-linux
 shell]# sh test7.sh 
请输入学生的成绩: dagfag
这不是一个数字请从新输入!!
[
root@hpf-linux
 shell]# sh test7.sh 
请输入学生的成绩: 89
良好!

通过上例可以看到case判断的使用,虽然例子不是很好,但是比较全面的练习了if和case语句,在编写时由于自己的马虎在判断句if [ ! -z $n1 ]中-z少写了- 导致出现了错误,请大家引以为戒!


八、shell脚本中的循环

1、for循环 

语法结构: for  变量名 in 条件; do … done ;


应用举例:

[
root@hpf-linux
 shell]# cat test8.sh 
#!/bin/bash
read -p "请输入一个数字:" n
n1=`echo $n | sed 's/[0-9]//g'`
if [  ! -z $n1  ]
then   echo "请输入数字!"
       exit 1
fi
sum=0
for i in `seq  1 $n`
do
   sum=$(($i+$sum))
done
   echo $sum
[
root@hpf-linux
 shell]# sh test8.sh -x
请输入一个数字:10
55
[
root@hpf-linux
 shell]# sh test8.sh -x
请输入一个数字:999
499500
[
root@hpf-linux
 shell]# sh test8.sh -x
请输入一个数字:99999
4999950000
[
root@hpf-linux
 shell]# sh test8.sh -x
请输入一个数字:5645757
15937288874403

上例为手动输入一个数计算其从0加到本身所得的总和并输出,在加最后一个数时CPU运算了二十多秒,所以没事还是不要这样玩。


2、while 循环

语法结构: while 条件; do … done 死循环用 : 表示 ;

break直接结束本层循环; continue忽略continue之下的代码,直接进行下一次循环 ;

exit 直接退出shell ;


应用举例:

[
root@hpf-linux
 shell]# cat test9.sh 
#/bin/bash
while :
do
   load=`w|awk -F 'load average: ' '{print$2}'|cut -d. -f1`
   processor=`cat /proc/cpuinfo | grep 'processor' | wc -l`
   if [ $load -lt $processor ]      //注意为了能收到邮件我写成小于,在长使用是用大于的
      then
 top -bn1|mail -s " load is high: $load"  XXXX
@126.com
  
   else
 exit 0
   fi
sleep 30
done

上例是一个简单的判断服务器是否过载,若过载则将信息发送给126邮箱,并且是30秒一封,这个例子是简单的通过脚本监控系统的负载,若要更好的监控还是建议使用专业的监控软件cacti/nagios/zabbix等工具。


[
root@hpf-linux
 shell]# cat test9.sh 
#/bin/bash
while :
do
   load=`w|awk -F 'load average: ' '{print$2}'|cut -d. -f1`
   processor=`cat /proc/cpuinfo | grep 'processor' | wc -l`
   if [ $load -lt $processor ]      //注意为了能收到邮件我写成小于,在长使用是用大于的
      then
 top -bn1|mail -s " load is high: $load"  XXXX
@126.com
  
   else
 exit 0
   fi
sleep 30
done

上例是简单的介绍使用在while语句中用同continue和break跳出循环的区别,简单的讲:

break :结束并退出循环 。

continue :在循环中不执行continue下面的代码,转而进入下一轮循环 

exit :退出脚本, 常带一个整数给系统,如 exit 0 

return :在函数中将数据返回,或返回一个结果给调用函数的脚本 


九、shell函数

1、shell函数简介

      shell一个非常重要的特性是它可作为一种编程语言来使用。因为shell是一个解释器,所以它不能对为它编写的程序进行编译,而是在每次从磁盘加载这些程序时对它们进行解释。而程序的加载和解释都是非常耗时的。针对此问题,许多shell(如BourneAgainShell)都包含shell函数,shell把这些函数放在内存中,这样每次需要执行它们时就不必再从磁盘读入。shell还以一种内部格式来存放这些函数,这样就不必耗费大量的时间来解释它们。


2、shell函数语法

函数由两部分组成:函数标题、函数体。 

标题是函数名。函数体是函数内的命令集合。标题名应该唯一;如果不是,将会混淆结果,因为脚本在查看调用脚本前将首先搜索函数调用相应的s h e l l。 

 定义函数的格式为:

 函数名()

{

命令1

 . . .

 }

或者

 函数名(){

命令1

 . . .

 }

两者方式都可行。如果愿意,可在函数名前加上关键字f u n c t i o n,这取决于使用者。

f u n c t i o n 函数名()

{ ...

 }

        可以将函数看作是脚本中的一段代码,但是有一个主要区别。执行函数时,它保留当前s h e l l和内存信息。此外如果执行或调用一个脚本文件中的另一段代码,将创建一个单独的 s h e l l,因而去除所有原脚本中定义的存在变量。 函数可以放在同一个文件中作为一段代码,也可以放在只包含函数的单独文件中。函数不必包含很多语句或命令,甚至可以只包含一个e c h o语句,这取决于使用者。参数返回,可以显示加:return 返回,如果不加,将以最后一条命令运行结果,作为返回值。 return后跟数值n(0-255)


3、shell函数应用举例

查看ip地址的函数;输入一个网卡名,输出网卡对应的ip地址;

[
root@hpf-linux
 shell]# cat fun1.sh 
#/bin/bash
read -p "请输入网卡:" network
ip () 
{ 
    ifconfig $network|head -2|tail -1|awk -F ':' '{print$2}'|awk '{print$1}'
}
case $network in
    eth*)
        echo "这是Ethernet网卡,"
        ipaddr=`ip $network`
        echo "$network的IP是:$ipaddr"
        ;;
      lo)
        echo "这是回环网卡"
        ipaddr=`ip $network`
        echo "$network的IP是:$ipaddr"
        ;;
       *)
        echo "你输入的不正确,请从新输入!"
        ;;
esac


扩展学习:

select也是循环的一种,它比较适合用在用户选择的情况下。

 比如,我们有一个这样的需求,运行脚本后,让用户去选择数字,选择1,会运行w命令,选择2运行top命令,选择3运行free命令,选择4退出。

#!/bin/bash
PS3="Please select a number: "
echo "Please chose a number, 1: run w, 2: run top, 3: run free, 4: quit"
echo
select command in w top free quit
do
    case $command in
    w)
        w
        ;;
    top)
        top
        ;;
    free)
        free
        ;;
    quit)
        exit
        ;;
    *)
        echo "Please input a number:(1-4)."
    esac
done
[root@hpf-linuxshell]# sh select1.sh 
Please chose a number, 1: run w, 2: run top, 3: run free, 4: quit
1) w
2) top
3) free
4) quit
Please select a number: 1
 09:34:03 up  9:39,  2 users,  load average: 0.00, 0.00, 0.00
USER     TTY      FROM              LOGIN@   IDLE   JCPU   PCPU WHAT
root     pts/0    192.168.1.104    00:22    0.00s  0.25s  0.00s sh select1.sh
root     pts/1    192.168.1.104    01:24   14:18   0.36s  0.36s -bash
Please select a number: 4

文件测试

  单目测试:
    -e file :测试文件是否存在
    -a file :测试文件是否存在
    -f file: 测试是否为普通文件
    -d 目录: 测试是否为目录文件
    -b somefile : 测试文件是否存在并且是否为一个块设备文件
    -c somefile : 测试文件是否存在并且是否为一个字符设备文件
    -h|-L somefile : 测试文件是否存在并且是否为符号链接文件
    -p somefile : 测试文件是否存在并且是否为管道文件:
    -S somefile : 测试文件是否存在并且是否为套接字文件:
    -r somefile:  测试其有效用户是否对此文件有读取权限
    -w somefile:  测试其有效用户是否对此文件有写权限
    -x somefile:  测试其有效用户是否对此文件有执行权限
    -s somefile:  测试文件是否存在并且不空
   双目测试:
    file1 -nt file2 :测试file1是否比file2更 新一些
    file1 -ot file2 :测试file1是否比file2更 老一些


你可能感兴趣的:(shell,基础)