bash脚本编程之判断和循环

前端之家收集整理的这篇文章主要介绍了bash脚本编程之判断和循环前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

bash脚本编程之判断和循环

变量:
      特性:一个变量中只能存储一个数值;

     数组:能够容纳多个数组元素的连续的内存空间;
   
      1)稀疏数组:
      2)稠密数组: 
 

    数组元素:数组中任何一个存放数据的存储单元,其作用相当于一个变量;

    数组元素的标识:
       
      索引数组标识:所有的数组元素都是使用数字编号的;
      通常数字标号是从0开始的,即:0,1,2....

    关联数组标识:所有的数组元素都可以使用名称(字符串)来标识;
      注意:bash4.0以上版本才有可能支持关联数组;

   数组声明定义:
      1.declare命令:
         -a	to make NAMEs indexed arrays (if supported)
           将其后的变量名称声明为索引数组;declare -a names=([0]='z'[1]='w' [2]='1')
         -A to make NAMEs associative arrays (if supported)
           将其后的变量名称声明为关联数组;declare -a names=( "z" "w" "l" )


     2.直接使用变量赋值的方式:
         定义稠密的索引数组
         ARRAY-NAME=(“VALUE1” “VALUE2”....)
         
         定义稀疏数组:
          ARRAY-NAME=([0]=“VALUE1” [1]=“VALUE2”....)

         定义关联数组:
           ARRAY-NAME=(INDEX_name1='VALUE1' INDEX_VALUE2='VALUE2'....)

     3.分别定义数组元素:
         ARRAY_NAME[0]='VALUE' 
         ARRAY_NAME[1]='VALUE'      
         ARRAY_NAME[2]='VALUE'
         .......



  引用数组元素的方式:
        ${ARRAY_NAME[INDEX]} 
        注意:在引用数组元素时,没人给出索引号,默认编号为”0“,即显示第一个数组元素的数值;
					

  引用整个数组中所有元素:
        ${ARRAY_NAME[*]}或 ${ARRAY_NAME[@]} 

  引用整个数组的所有元素的索引号:
        ${!ARRAY_NAME[*]}或 ${!ARRAY_NAME[@]}

  查看数组中的元素个数(数组长度):
       ${#ARRAY_NAME[*]}或 ${#ARRAY_NAME[@]}




  数组切片:
        ${ARRAY_NAME[*]:offset}
          //显示包括offste数值所对表示的位置的元素极其后所有的元素;
        
        ${ARRAY_NAME[*]:offset:number}
          //显示数组中包括offset数值所对应表示的位置的元素及其后number个元素;

  数组撤销:
        unset ARRAY_NAME
   


  RANDOM变量:
        随机数变量:0-32767,整数值;
      
        从熵池中取随机数;
      

        熵池:
        /dev/random
          两次敲击键盘的时间间隔;
          两次IO的时间间隔;
          ...
        /dev/urandom:伪熵池
          利用应用程序计算得到的随机数;
						[root@localhost ~]# echo $RANDOM
         25570
         [root@localhost ~]# echo $RANDOM
         8882
         [root@localhost ~]# echo $RANDOM
         2373
        [root@localhost ~]# echo $RANDOM
        4870
       [root@localhost ~]# echo $RANDOM
        3895
       [root@localhost ~]# echo $RANDOM
        8353
      [root@localhost ~]# echo $RANDOM
       14099







 bash脚本编程的结构:
   bash脚本编程语言:
        脚本类语言
        解释型语言
        过程式编程语言



      过程式编程语言结构:
       顺序执行结构:默认
         从上而下,自左而右地执行所有的语句(命令);
  
       选择执行结构:
         当条件满足或不足时,才会执行对应的语句(命令);
       
       循环执行结构:
         重复执行某段语句(命令);    
   
   bash脚本编程语中也具有上述结构;
        顺序执行结构:默认
       
       选择执行结构:
        根据给定条件逻辑判断结果或根据某个可选取的取值范围,进而选择某个分支结构中的命令语句予以执行的方式;
       if:
         选择执行结构的标准,根据条件的逻辑判断结果选择执行的语句内容;
       case:
         选择执行结构的标准,根据符合某特定范围的取值标准选择执行的语句内容;
       
       循环执行结构:
        对于特定语句内容 ,重复执行0,1,多次;
        
       for:以遍历列表的方式进行循环;
       while:根据给定条件的逻辑判断结果进行循环,逻辑判断结果为真,循环,否则,停止循环;   
       until:根据给定条件的逻辑判断结果进行循环,逻辑判断结果为假,循环,否则,停止循环;
       select:死循环,即没有默认退出条件的循环;利用循环提供一个可选择的列表;





 bash脚本的执行结构之if选择执行结构:
      if语句:if - if COMMANDS; then COMMANDS; [ elif COMMANDS; then COMMANDS; ]... [ else COMMANDS; ] fi

	if语句的单分支结构:
		if - if COMMANDS; then COMMANDS; fi

		注意:是否会执行then后面的命令,取决于if后面的命令的执行状态返回值:
			1.如果其返回值为真,则执行then后面的命令;
			2.如果其返回值为假,则不执行then后面的命令;



      建议在脚本中的书写格式:
       if CONDITION ; then
         statement
          ...
       fi 

       或
       
       if  CONDITION
        
       then
         
         STATEMENT
         ....
       fi





        
       if语句的双分支结构:
        if - if COMMANDS; then COMMANDS; else COMMANDS; fi
        

        注意:是否执行then后的命令或else后的命令,取决于if后的命令执行状态的返回值;
        1.如果返回值为真,则执行then后的命令;
        2.如果为假,则执行else后的命令;


       if语句的多分支结构:

         if - if COMMANDS; then COMMANDS; else COMMANDS; fi
       
        注意:是否执行then后的命令或else后的命令,取决于if后的命令执行状态的返回值或else后的命令执行状态返回值;
        
        1.首先判断if后的命令的状态返回值是否为真,为真就执行then后的语句;如果为假,就继续判断第一个elif后的命令
          执行状态返回值;
        2.第一个elif后的命令执行状态返回值为真,就执行第一个elif语句中then后的命令,否则,就继续判断第二个elif后的
          执行状态返回值;
       3.以此类推,会判断每个elif后面的命令的执行状态返回值是否为真;如果所有的if和elif后面的命令的执行状态返回值均为假,则执行else后面的语句;

		建议在脚本中的书写格式:
			if CONDITION1 ; then
				STATEMENT
				...
			elif CONDITION2 ; then
				STATEMENT
				...
			elif CONDITION3 ; then
				STATEMENT
				...
			...
			else
				STATEMENT
				...
			fi
			或
			if CONDITION
			then
				STATEMENT
				...
			elif CONDITION2 ; then
				STATEMENT
				...
			elif CONDITION3 ; then
				STATEMENT
				...
			...
			else
				STATEMENT
				...
			fi



       注意:if的多分支结构,使用场景不多,而且有时候,可以使用嵌套的多分支或双分支if结构代替if多分支结构;


       嵌套的if结构
         if CONDITION1 ; then
            if CONDITION2 ; then
               if CONDITION3 ; then
                STATEMENT
                ...
               
               else
                STATEMENT
                ...
            
            else
             STATEMENT
              ...
              fi
        
         else
          STATEMENT
          ...
          fi


     COMMAND1 && COMMAND2 || COMMAND3




    示例:
      写脚本,判断某个用户的默认登录shell是否为/bin/bash
      
      #!/bin/bash
      y=$(cut -d: -f 1 /etc/shadow | sort -R | head -1)
      w=$(egrep "^$y\>" /etc/passwd | cut -d: -f 7)
      if [ "$w"=="/bin/bash" ] ; then
          echo "${y}'s login shell is /bin/bash."
      else
          echo "${y}'s login shell is ${w}"
      fi
      
      unset y w


    

     bash脚本编程之用户交互使用:
       位置参数变量:
       $0:命令的本身,对于脚本而言,就是该脚本的路径;
       $1,$2,....$N:脚本后面通过命令行给脚本传递的命令行参数;
         N>9时,引用该位置变量时需要加{},即${10}



      特殊变量:
      $@:给出的所有位置的参数的列表,当使用双引号时,每个参数作为单独的字符串存在;
      $*:给出的所有位置的参数的列表,当使用双引号时,每个参数作为单独的字符串存在;
      $#:表示除去$0之外,整个命令行中有多少个参数;


      

   
 
     read命令:
       read [-ers] [-a 数组] [-d 分隔符] [-i 缓冲区文字] [-n 读取字符数] 
            [-N 读取字符数] [-p 提示符] [-t 超时] [-u 文件描述符] [名称 ...]
        
        -a array:定义数组(索引数组);
        -p prompt:给用户输出提示信息;
        -t timeout:用户输入的超时时间;
         name :变量或数组的名称;如果省略此内容,bash会将read读到的信息直接保存到内置的名为REPLAY变量中;
 
    
     注意:
        Linux思想之一:尽量不与用户交互;
     

        在使用read命令时,通常会使用-t选项来指定与用户的交互时间,一旦超过预定时间,脚本中后续的命令内容自动被执行;因此,通常需要在后面判断通过read赋值的变量值是否为空,如果为空,可能为该变量提供默认值;
         
        read -t 5 VAR1
          [ -z $VAR1 ] && VAR1=value1

     



   管理用户脚本:
   脚本可以接受两个参数,第一个参数为-a或-d,第二个参数为用户名;如果第一个参数是-a,则创建其后面参数命名的用户;如果第一个参数为-d,则删除其后面参       数命名的用户;

     #!/bin/bash
     #
    if [ $# -ne 2 ] ; then
    echo "Make sure provide TWO arguments."
      exit 5
      fi

    if [ $1 == '-a' ] ; then
      if ! id $2 &> /dev/null ; then
        useradd $2 &> /dev/null
        echo $2 | passwd --stdin $2 &> /dev/null
        echo "User $2 created succesfully and password changed to it's username."
      else
        echo "$2 exists already."
      fi
    elif [ $1 == '-d' ] ; then
      if id $2 &> /dev/null ; then
        userdel -r $2 &> /dev/null
        echo "User $2 delete finished."
      else
        echo "$2 does not exist yet."
      fi
      else
        echo "Usage: $(basename $0) -a USERNAME | -d USERNAME"
      exit 6
    fi

改进版:使用read命令; #!/bin/bash

if [ $# -ne 1 ] ; then echo "Make sure provide ONE argument." exit 5 fi

if [ $1 == '-a' ] ; then read -p "Please input a username for creating: " USERNAME if ! id $USERNAME &> /dev/null ; then useradd $USERNAME &> /dev/null echo $USERNAME | passwd --stdin $USERNAME &> /dev/null echo "User $USERNAME created succesfully and password changed to it's username." else echo "$USERNAME exists already." fi elif [ $1 == '-d' ] ; then read -p "Please input a username for deleting: " USERNAME read -t 5 -p "confirm? Input 'yes' to continue: " CHOICE [ -z $CHOICE ] && CHOICE='no'

if [ $CHOICE == 'yes' ] ; then if id $USERNAME &> /dev/null ; then userdel -r $USERNAME &> /dev/null echo "User $USERNAME delete finished." else echo "$USERNAME does not exist yet." fi else echo echo "$USERNAME is not deleted." fi else echo "Usage: $(basename $0) { -a | -d }" exit 6 fi

写脚本解决问题: 1.判断用户通过命令行给的一个参数是否为整数。

#!/bin/bash

if [ $# -ne 1 ] ; then echo "Make sure provide ONE digit." exit 5 fi

if [[ $1 =~ ^[[:digit:]]+$ ]] ; then echo "$1 is a pure digit." else echo "$1 is not a digit." fi

循环执行结构:
       循环:将某一段代码或命令重复执行0,1或多次;



       一个好的循环结构,必须要包括两个重要的环节:
        1.进入循环的条件:
          在符合要求或满足条件时才开始循环;

        2.退出循环条件:
          达到某个要求或符号某个条件时需要结束或终止循环的执行;





    for循环:
       1.遍历列表的循环:
         for 名称 [in 词语 ... ] ; do 命令; done
         为列表中的每个成员执行命令。


         建议在脚本中的书写格式:
         for VAR_NAME in LIST ; do
           循环体
         done
         或
         for VAR_NAME in LIST 
         do
            循环体
         done


         注意:
         VAR_NAME:任意指定的变量名称,变量的值是从LIST中遍历获取的各个元素;
         LIST:for循环需要遍历的列表,可以通过如下方式生成列表:
            1.直接给出列表;
            2.纯整数列表:
              1):花括号展开:
                   {FIRSTNUM..LASTNUM}
                    
              2):seq命令
                    seq [OPTION]... LAST  seq 10

                    seq [OPTION]... FIRST LAST  seq 2 6

                    seq [OPTION]... FIRST INCREMENT LAST   seq 0 2 20
            
           3.花括号展开
                   {FIRST..LAST}

           4.命令的执行结果:
             ls /etc
           

           5.GLOBBING通配符
      
           6.某些特殊变量的值:
             $*,$@



          循环体:
          
            一般来说,循环体中应该包括能够用到VAR_NAME变量的值的命令或命令的组合;如果循环体中的命令没有用到
            VAR_NAME变量的值的话,列表的元素的个数就是此次for循环的次数;
 
            #!/bin/bash
            for i in {1..50} ; do 
            sum=$[sum+i]
            done
            echo "$sum" 

  
       例子:给脚本传递三个整数,要求:
1) 如果用户传递过来的不是三个参数,报告正确用法;
2) 如果三个参数中有非纯数字字符串,报告错误提示用户输入数字;
3) 从三个整数中的选出最大数和最小数,并显示出来;
4) 不能使用sort命令等排序;
[root@localhost ~]# vim a.sh
#!/bin/bash
#
if [ $# -ne 3 ] ; then
   echo " please provide three argument"
   exit 5
fi
if [[ $1 =~ [^[:digit:]] ]]||[[ $2 =~ [^[:digit:]] ]] ||[[ $3 =~ [^[:digit:]] ]] ; then
   echo "exist error"
fi
if [ $1 -ge $2 ] ; then
    if [ $1 -ge $3 ] ; then
       echo "the largest is $1"
    fi
fi
if [ $2 -ge $1 ] ; then
    if [ $1 -ge $3 ] ; then
      echo "the largest is $2"
    fi
fi
if [ $3 -ge $1 ] ; then
   if [ $3 -ge $2 ] ; then
     echo "the largest is $3"
   fi
fi
if [ $1 -le $2 ] ; then
   if [ $1 -le $3 ] ; then
     echo "the smallest is $1"
   fi
fi
if [ $2 -le $1 ] ; then
   if [ $2 -le $3 ] ; then
     echo "the smallest is $3"
   fi
fi
if [ $3 -le $1 ] ; then
  if [ $3 -le $2 ] ; then
    echo "the largest is $3"
  fi
fi

结果:
 [root@localhost ~]# bash a.sh  12  13 14
 the largest is 14
 the smallest is 12

例:给脚本传递一个整数,分别计算该整数以内所有偶数之和以及奇数之和。 [root@localhost ~]# vim q.sh #!/bin/bash declare i sum=0 sum1 if [[ $1 =~ [^[:digit:]] ]] ;then echo "$1should be an integer" exit 5 fi if [ "$1" -eq 1 ] ; then echo "奇数和为1" exit 5 fi if [ "$1" -eq 2 ] ; then echo "偶数和为2" exit 5 fi

for i in $(seq 1 2 $1) ; do sum=$[sum+i]

done
echo "奇数和为$sum"
for i in $(seq 2  2 $1 ) ; do
sum1=$[sum1+i]

done
echo "偶数的和为$sum1"

结果:[root@localhost ~]# bash q.sh 3 奇数和为4 偶数的和为2 [root@localhost ~]# bash q.sh 5 奇数和为9 偶数的和为6

例:      
8.利用RANDOM变量随机生成十个数字,显示出这十个数字,并显示出其中的最大值和最小值。

[root@localhost ~]# vim 000

#!/bin/bash

touch ytc for i in $( seq 1 10 ) ; do echo $RANDOM &>> ytc done sort -n ytc| head -1 sort -n ytc| tail -1 rm -r ytc

结果: [root@localhost ~]# bash 000 7119 28639 [root@localhost ~]# bash 000 412 31953

例:给脚本传递一个数字作为行总数,分别打印由*组成的最小锐角朝上和朝下的等腰三角形以及菱形。
  角朝下

[root@localhost ~]# vim 9 #!/bin/bash

if [ $# -ne 1 ] ; then echo " usage: $(basename $0) integer" exit 5 fi

if [[ $1 =~ [^[:digit:]] ]] ; then echo " usage: $(basename $0) integer" exit 5 fi

linenum=$1 for i in $(seq $linenum) ; do for j in $(seq $[i-1 ]); do echo -n " " done for k in $(seq $[2*(linenum-i)+1 ]) ; do echo -n "*" done echo done

结果:[root@localhost ~]# bash 9 8





*******
 *****
  ***
   *

角朝上: [root@localhost ~]# vim 10 #!/bin/bash

if [ $# -ne 1 ] ; then echo "Usage: $(basename $0) INTEGER" exit 5 fi

if [[ $1 =~ [^[:digit:]] ]] ; then echo "Usage: $(basename $0) INTEGER" exit 6 fi

linenum=$1 for i in $( seq $linenum) ; do for j in $( seq $[linenum-i]) ; do echo -n " " done for k in $(seq $[2*i-1]) ; do echo -n "*" done echo done

结果: [root@localhost ~]# bash 10 8 * *** ***** *******





菱形: [root@localhost ~]# vim 11 #!/bin/bash

if [ $# -ne 2 ] ; then echo "Usage: $(basename $0) INTEGER" exit 5 fi

if [[ $1 =~ [^[:digit:]] ]] ; then echo "Usage: $(basename $0) INTEGER" exit 6 fi

linenum=$1 for i in $( seq $linenum) ; do for j in $( seq $[linenum-i]) ; do echo -n " " done for k in $(seq $[2*i-1]) ; do echo -n "*" done echo done

linenum=$2

for i in $(seq $linenum) ; do for j in $(seq $[i ]); do echo -n " " done for k in $(seq $[2*(linenum-i)+1 ]) ; do echo -n "*" done echo done

结果: [root@localhost ~]# bash 11 8 7 * *** ***** *******








*******
 *****
  ***
   *

例:分别打印顺序和旋转的九九乘法表。 1)顺序的九九乘法表是正常的九九乘法表; [root@localhost ~]# vim 8 #!/bin/bash

for i in {1..9} ; do
     for j in $(seq $i) ; do
     echo -ne "$i×$j=$[i*j]\t"
     done
     echo
  done


   2)旋转的九九乘法表是第一行是1×1=1 1×2=2 1×3=3 1×4=4 ... 1×9=9; 第二行是2×2=4 2×3=6 2×4=8 ... 2×9=18; ... 第九行是9×9=81;
 [root@localhost ~]# vim 7
  #!/bin/bash
  
  for i in {1..9} ; do
     for j in $(seq $i 9) ; do
     echo -ne "$i×$j=$[i*j]\t"
     done
     echo
  done

  结果:
  [root@localhost ~]# bash 7

1×1=1 1×2=2 1×3=3 1×4=4 1×5=5 1×6=6 1×7=7 1×8=8 1×9=9 2×2=4 2×3=6 2×4=8 2×5=10 2×6=12 2×7=14 2×8=16 2×9=18 3×3=9 3×4=12 3×5=15 3×6=18 3×7=21 3×8=24 3×9=27 4×4=16 4×5=20 4×6=24 4×7=28 4×8=32 4×9=36 5×5=25 5×6=30 5×7=35 5×8=40 5×9=45 6×6=36 6×7=42 6×8=48 6×9=54 7×7=49 7×8=56 7×9=63 8×8=64 8×9=72 9×9=81

总结:
         1.进入循环的条件:LIST中还有未被取尽的元素;
         2.退出循环的条件:LIST中的元素被取尽;
         3.for循环几乎不会出现死循环;
         4.在执行循环的过程中,需要将整个LIST载入内存,因此对于大列表来说,可能会消耗较多的内存及cpu资源;

编程思想: 将人类的自然语言转换成程序的代码语言的方式;

DevOPS

不会开发的运维是没有出路的。

流程图

如果 a大于3, 那么 创建一个用户 fi

原文链接:https://www.f2er.com/bash/389455.html

猜你在找的Bash相关文章