shell脚本进阶 详解及其实例

前言

一、条件选择、判断(if、case)

1.1 if语句用法及实例

1.2 case用法及实例

二、循环语句

2.1 for循环

2.2 while循环

2.3 until循环

2.4 select循环

2.5 循环小补充

2.5.1 循环控制语句 continue&break

2.5.2 循环控制命令shift

2.5.3 信号捕捉trap

2.5.4 创建无限循环

2.5.5 在循环语句中执行并行命令

三、小补充

1)打印等腰三角形(带闪烁)

2)打印国际象棋棋盘

 

 

 

 

前言

在我们使用linux的过程中,脚本可以给我们省很多时间和精力,比如,我们要定期备份一些文件,如果我们纯手工去操作的话,每到一个时间段我们就要去进行备份的操作,如果某一次我们在干其他事情的时候,把这件事情忘了那可怎么办╮(╯﹏╰)╭这个时候,我们就可以把需要执行的备份命令放在一个脚本里面,通过一些语句去判断是否符合我们执行命令的条件,实现自动化0.0这样不就省时省心很多啦~老板再也不用担心我忘记备份ヽ( ̄▽ ̄)ノ那么,接下来,小编就来分享一下脚本的语法及实例。

一、条件选择、判断(if、case)

1.1 if语句用法及实例

当我们在脚本中遇到需要判断的时候,我们就可以用if语句来实现。具体的语法如下:

  •    单分支

    if 判断条件;then

    条件为真的分支代码 
  fi

  •    双分支

if 判断条件; then

条件为真的分支代码

else

条件为假的分支代码

fi

  •    多分支

if 判断条件1; then

条件为真的分支代码
elif 判断条件2; then

条件为真的分支代码
elif 判断条件3; then

条件为真的分支代码

else

以上条件都为假的分支代码
fi

在多分支中,系统会逐条判断你写入的条件,第一次遇到“真”条件时,执行该分支,而后结束整个if语句。

注意:1、if和fi是成对出现的

2、if语句可以嵌套。

Example:

1)判断两个数字的大小

复制代码
 1 #!/bin/bash 2 #定义变量 3 read -p "Please input the first num:" num1 4 read -p "Please input the second num:" num2 5 #判断数字是否符合标准 6 if [[ $num1 =~ ^[0-9]+$ && $num2 =~ ^[0-9]+$ ]];then 7 #    判断两个数字的大小并输出判断结果 8     if [ $num1 -lt $num2 ];then 9         echo "The num2 is biger than the num1"10     elif [ $num1 -eq $num2 ];then11         echo "Two numbers equal"12     else 13         echo "The num1 is biger than the num2"14     fi15 else16     echo "Please enter the correct number"17 fi18 19 #删除变量20 unset num1 num2
复制代码

 shell脚本进阶 详解及其实例_第1张图片

 

2)编写脚本/root/bin/createuser.sh,实现如下功能:使用一个用户名做为参数,如果指定参数的用户存在,就显示其存在,否则添加之;显示添加的用户的id号等信息

复制代码
 1 #!/bin/bash 2 #定义变量 3 read -p "请输入一个用户名:" name 4 #判断用户名是否存在 5 if  `id $name &> /dev/null`;then 6 #    若存在,则输出ID等信息 7 echo "用户存在,用户的ID信息为:`id $name`" 8 else 9 #    若不存在,则添加用户,设置密码为随机8位,下次登录时提示修改密码,同时显示ID等信息10 passwd=`cat /dev/urandom |tr -cd [:alpha:] |head -c8`11 `useradd $name &> /dev/null`12 `echo "$passwd" | passwd --stdin $name &> /dev/null`13 echo "用户名:$name 密码: $passwd" >> user.txt14 `chage -d 0 $name`15 echo "用户已添加,用户的ID信息为:`id $name` 密码为:$passwd"16 fi17 18 #删除变量19 unset name passwd
复制代码

 

 

1.2 case用法及实例

当涉及到多个条件匹配的时候,我们用if可能就很麻烦了,这个时候,我们就可以用case来编写这个脚本。case的具体语法如下:

case 变量引用 in

PAT1)

分支1

;;

PAT2)

分支2

;;

...

*)

默认分支

;;

esac

注意:1、case每一个分支后,都是以两个“;”结尾的(最后一个可以省略)

      2、case和esac是成对出现的

Example:

1)编写一个脚本,提示用户输入信息,判断其输入的是yes或no或其他信息。

复制代码
 1 #!/bin/bash 2 #定义变量 3 read -p "Yue ma?(yes or no):" ANS  4 #把变量中的大写转换为小写 5 ans=`echo "$ANS" |tr [[:upper:]] [[:lower:]] ` 6 #判断输入的信息是什么并输出结果 7 case $ans in 8 yes|y) 9     echo "see you tonight"10     ;;  11 no|n)12     echo "sorry,I have no time"13     ;;  14 *)15     echo "what’s your means?"16     ;;  17 esac18 19 #删除变量20 unset ANS ans
复制代码

 shell脚本进阶 详解及其实例_第2张图片

 

2)编写脚本/root/bin/filetype.sh,判断用户输入文件路径,显示其文件类型(普通,目录,链接,其它文件类型)

复制代码
 1 #!/bin/bash 2 read -p "请输入一个文件路径:" file 3 #判断文件是否存在 4 `ls $file &> /dev/null` 5 #若存在,判断文件类型并输出 6 if [ $? -eq 0 ];then 7     style=`ls -ld $file | head -c1` 8     case $style in 9     -)  10         echo "这是一个普通文件"11         ;;  12     d)  13         echo "这是一个目录文件"14         ;;  15     l)  16         echo "这是一个链接文件"17         ;;18     *)19         echo "这是其他类型文件"20         ;;21     esac22 #若不存在,提示并退出23 else24     echo "该文件不存在"25     exit 226 fi27 28 #删除变量29 unset file style
复制代码

 shell脚本进阶 详解及其实例_第3张图片

 

二、循环语句

    在我们的脚本中,肯定也少不了对某一段代码重复运行多次的操作,此时,我们就会用到循环语句。循环语句中,都是有进入条件退出条件的,循环的次数也分为事先已知事先未知(事先已知就是我们知道循环的具体次数,事先未知则是指当满足某一条件就进行循环,但是次数是不确定的。)。接下来,我们就来看看关于循环语句的用法。

2.1 for循环

for循环的执行机制是:一次将列表中的元素赋值给“变量名”;每次赋值后即执行一次循环体;直到列表中的元素耗尽,循环结束。基本的语法有两种:

1)for 变量名 in 列表 ; do

循环体

done

关于列表的生成方法,如下:

①直接给出列表

②整数列表:

(a){start…end}

(b)`seq start end`

③返回列表的命令

    $(COMMAND)

④使用glob通配符如:

      *.sh

⑤变量引用

$i,$*

2)for (( exp1; exp2; exp3 )); do

循环体

done

   更清晰的可以从下图中看出:

shell脚本进阶 详解及其实例_第4张图片

 

Example:

1)打印九九乘法表

复制代码
 1 #!/bin/bash 2 #判断i的值是否在1-9 3 for i in {1..9};do 4 #   判断j的值是否在1-$i 5 for j in `seq 1 $i`;do 6 #       若在,则打印i*j的值 7         echo -en "$i*$j = $[$i*$j]\t"  8     done 9     echo10 done11 12 #删除变量13 unset i j
复制代码

 shell脚本进阶 详解及其实例_第5张图片

 

2)输入正整数n,计算1+…+n的和

复制代码
 1 #!/bin/bash 2 #定义变量 3 sum=0 4 read -p "请输入一个正整数:" num  5 #判断num是否是正整数 6 if [[ $num =~ ^[[:digit:]]+$ ]];then 7 #   若是,当i在1-$num时,输出sum值 8     for i in `seq 1 $num`;do 9         let sum+=$i    10     done 11         echo "sum=$sum"12 #若不是,提示输出正整数13 else 14     echo "请输入一个正整数!"15 fi16 17 #删除变量18 unset i sum num
复制代码

 shell脚本进阶 详解及其实例_第6张图片

 

2.2 while循环

while循环比for循环略复杂一些,具体语法如下:

while CONDITION; do

      循环体

done

注意:1、进入条件:CONDITION为true;退出条件:CONDITION为false。

      2、CONDITION为循环控制条件:进入循环之前,先做一次判断;每一次循环之后会再次做判断;条件为“true”,则执行一次循环;知道条件测试状态为“false”终止循环。

      3、CONDITION一般应该有循环控制变量;此变量的值会在循环体不断地被修正。

Example:

1)计算100以内所有正奇数之和

复制代码
 1 #!/bin/bash 2 #定义变量 3 i=1 4 sum=0 5 #当i<100时,执行下面语句 6 while [ $i -le 100 ];do 7 #当i为奇数时,另sum=sum+I,i=i+1 8     while [ $[i%2] -eq 1 ];do 9         let sum+=$i10         let i+=1 11 done12 #   当i不为奇数时,i=i+113     let i+=114 done15 #输出结果16 echo "sum=$sum"17 18 #删除变量19 unset i sum
复制代码

 

 

2.3 until循环

   until循环的语法和while的语法类似,但是进入和退出的条件却刚好相反,所以不常用,只要我们了解即可。具体语法如下:

until CONDITION; do

   循环体

done

注意:1、进入条件:CONDITION为false;退出条件:CONDITION为true。

     2、do和done成对出现。

Example:

1)循环输出1-10

复制代码
 1 #!/bin/bash 2 #定义变量 3 i=1 4 #当i>10时,退出循环 5 until [ $i -gt 10 ];do 6 #   输出i的值,i=i+1 7     echo $i  8     let i+=1 9 done10 11 #删除变量12 unset i 
复制代码

shell脚本进阶 详解及其实例_第7张图片

 

2.4 select循环

   select循环主要用于创建菜单,按数字顺序排列的菜单项将显示在标准错误上,并显示PS3提示符,等待用户输入。

   用户输入菜单列表中的某个数字,执行相应的命令。

   用户输入被保存在内置变量REPLY中。

   select的具体语法如下:

select variable in list; do

   循环体命令

done

注意:①select是个无线循环,因此要记住用break命令退出循环,或用exit命令终止脚本。也可以按ctrl+c退出循环。

②select经常和case联合使用。

③与for循环类似,可以省略in list,此时使用位置变量。

Example:

1)生成菜单,并显示选中的价钱。

复制代码
 1 #!/bin/bash 2 #定义PS3提示符 3 PS3="Please choose the menu:" 4 #输出菜单 5 select menu in yangroutang mifan hulatang jiaozi lamian huimian quit 6 do 7 #   判断选择 8     case $REPLY in 9     1|4)10         echo "The price is 20"11         ;;  12     2|5)13         echo "The price is 12"14         ;;  15     3|6)16         echo "The price is 10"17         ;;  18     7)  19         break20         ;;  21     *)  22         echo "Choose error"23         ;;  24     esac25 done
复制代码

shell脚本进阶 详解及其实例_第8张图片

 

2.5 循环小补充

2.5.1 循环控制语句 continue&break

   循环控制语句用于循环体中,常见的控制语句有两种,continue和break。接下来我们就来看看两者的区别:

continue语句结束的是本轮循环,直接进入下一轮判断;最内层是第1层。

break语句结束的则是整个循环,最内层为第1层。

Example:

1)求(1+3+…+49+53+…+99)的和

复制代码
 1 #定义变量 2 sum=0 3 for ((i=1;i<=100;i++));do 4 #   当i为奇数时,继续执行 5     if [ $[i%2] -eq 1 ];then 6 #       当i=51时,跳过该循环 7         if [ $i -eq 51 ];then 8             continue 9         fi  10         let sum+=$i11     fi  12 done13 echo "sum=$sum"14 15 #删除变量16 unset i sum
复制代码

 

2)求(1+3+…+49)的和

复制代码
 1 #!/bin/bash 2 #定义变量 3 sum=0 4 for ((i=1;i<=100;i++));do 5 #   当i为奇数时,继续执行 6     if [ $[i%2] -eq 1 ];then 7 #       当i=51时,跳出整个循环 8         if [ $i -eq 51 ];then 9             continue10         fi  11         let sum+=$i12     fi  13 done14 echo "sum=$sum"15 16 #删除变量17 unset i sum
复制代码

 

2.5.2 循环控制命令shift

   位置参数可以用shift命令左移,比如shift 3表示原来的$4现在变成$1,原来的$5现在变成$2等等,原来的$1,$2,$3丢弃,$0不移动。不带参数的shift命令相当于shift 1。

   我们知道,对于位置变量或命令行参数,其个数必须是确定的,或者当shell程序不知道其个数时可以把所有参数一起赋值给变量$*。当用户要求shell在不知道位置变量个数的情况下,还能逐个的把参数一一进行处理,也就是在$1后为$2等。在shift命令执行前变量$1的值在shift命令执行后就不可用了。

Example:

1)测试shift命令

1 #!/bin/bash2 until [ $# -eq 0 ];do3     echo "The first argument is:$1,The number of arguments is:$#"4     shift5 done

 

2.5.3 信号捕捉trap

   trap是一个shell内建命令,它用来在脚本中指定信号如何处理。比如,按Ctrl+C会使脚本终止执行,实际上系统发送了SIGINT信号给脚本进程,SIGINT信号的默认处理方式就是退出程序。如果要在Ctrl+C不退出程序,那么就得使用trap命令来指定一下SIGINT的处理方式了。trap命令不仅仅处理Linux信号,还能对脚本退出(EXIT)、调试(DEBUG)、错误(ERR)、返回(RETURN)等情况指定处理方式。

   基本格式语法如下:

  •    trap ‘触发指令’ 信号

   自定义进程收到系统发出的指定信号后,将执行触发指令,而不是执行原操作

  •        trap ‘’ 信号

   忽略信号的操作

  •    trap ‘-’ 信号

   恢复原信号的操作

  •        trap -p

   列出自定义信号的操作,即提示当前使用的trap操作是什么。

注意:①信号的表示方法:可以是完整信号/简写/数字(具体内容通过kill -l查询)

②信号9,强制杀死,捕获不到。

Example:

1)打印0-9,ctrl+c终止无效

复制代码
1 #!/bin/bash2 #设置信号捕获3 trap 'echo press ctrl+c' 24 for ((i=0;i<10;i++));do5     sleep 16     echo $i7 done
复制代码

shell脚本进阶 详解及其实例_第9张图片


2)打印0-9,3之前ctrl+c不能终止,3之后恢复,能终止

复制代码
 1 #!/bin/bash 2 #设置信号捕获 3 trap '' 2 4 trap -p 5 for ((i=0;i<3;i++));do 6     sleep 1 7     echo $i 8 done 9 trap '-' SIGINT10 for ((i=3;i<10;i++));do11     sleep 112     echo $i13 done
复制代码

shell脚本进阶 详解及其实例_第10张图片


2.5.4 创建无限循环

   在我们的shell脚本中,可以创建一个死循环,具体设置如下:

   while true;do

     循环体

   done

 

2.5.5 在循环语句中执行并行命令

   当我们需要在脚本里执行一条命令很多次的时候,我们可以将其设置为并行执行,这样可以极大的提升脚本运行速度,但是也有缺点,并行执行的话,相当于开了很多子shell一起执行,运行速度上来了,但是对资源的消耗也增多了

   具体的用法示例如下:

   for name in 列表; do

     {

        循环体

}$

   done

   wait

Example:

1)搜寻自己指定的的IP(子网掩码为24的)的网段中,up的ip地址

复制代码
 1 #!/bin/bash 2 #定义变量 3 read -p "Please input network (eg:172.17.0.1): " net echo $net |egrep -o "\<(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\>" 4 #判断网段是否符合规范 5 [ $? -eq 0 ] || ( echo "input error";exit 10 ) 6 #判断网段内哪些IP能ping通,并行执行 7 IP=`echo $net |egrep -o "^([0-9]{1,3}\.){3}"` 8 for i in {1..254};do 9      {   10          ping -c 1 -w 1 $IP$i &> /dev/null && \11          echo "$IP$i is up" 12      }&  13 done14 wait15  16 #删除变量17 unset net IP i
复制代码

shell脚本进阶 详解及其实例_第11张图片

 

三、小补充

      介绍了这么多语法,我们来玩一些好玩的吧~下面是小编给大家分享的几个有意思的脚本

1)打印等腰三角形(带闪烁)

复制代码
 1 #!/bin/bash 2 #num=总行号  i=第几行  j=*个数  k=空格个数 3 read -p "请输入一个数字:" num  4 for i in `seq 1 $num`;do 5     for k in `seq 1 $[$num-$i]`; do 6         echo -n " " 7     done 8     for j in `seq 1 $[2*$i-1]`;do 9         if [ $j -eq 1 ] || [ $j -eq $[2*$i-1] ] || [ $i -eq $num ];then10             color=$[RANDOM%5+31]11             echo -en "\033[1;$color;5m*\033[0m"12         else13             echo -n "*"14         fi  15     done16     echo17 done18 19 #删除变量20 unset num i j k color
复制代码

          具体的效果大家可以自己去尝试,就是下面两张图配合出来的效果:

shell脚本进阶 详解及其实例_第12张图片 shell脚本进阶 详解及其实例_第13张图片


2)打印国际象棋棋盘

复制代码
 1 #!/bin/bash 2 #定义变量 3 color_1="\033[1;44m  \033[0m" 4 color_2="\033[1;45m  \033[0m" 5 for (( i=1;$i <=8;i++ ));do 6     for (( j=1;$j <=8;j++ ));do 7         if [ $[$i%2] == 1 ] && [ $[$j%2] == 1 ];then 8             echo -en "$color_1$color_2" 9         elif [ $[$i%2] == 0 ] && [ $[$j%2] == 0 ];then10             echo -en "$color_2$color_1"11         fi  12     done13     echo14 done15 16 #删除变量17 unset color_1 color_2 i j
复制代码

你可能感兴趣的:(shell脚本进阶 详解及其实例)