bash脚本编程的结构:

   (bash脚本编程语言是脚本类语言、解释型语言、过程式编程语言。


   过程式编程语言的结构:

      顺序执行结构(默认):

        从上到下,自左而右的执行所有的语句(命令)

      选择执行结构:

        当条件满足或不满足时,才会执行对于的语句(命令)

      循环执行结构:

        重复执行某段语句(命令)


   在bash脚本编程语言中也具备上述结构:

      顺序执行结构:bash默认的执行结构


      选择执行结构:

        根据给定的条件的逻辑判断结果或根据某个可选取的取值范围进而选择某个分支结构中的语句(命令)予以执行;

          if:分支选择执行结构的标准,根据条件的逻辑判断结果来选择执行的语句内容;

          case:选择执行结构的标准,根据符合某特定范围的取值标准来选择执行的语句内容;


      循环执行结构:对于结构内的特定语句内容,重复执行0次,1次或多次;

        for循环:遍历列表的方式来进行循环;

        while循环:根据给定的逻辑判断结果来进行循环;逻辑判断结果为真才循环,否则停止循环;

        until循环:根据给定的逻辑判断结果来进行循环;逻辑判断结果为假才循环,否则停止循环;

        select循环:死循环,即没有默认退出条件的循环;利用循环提供一个可选择的列表;



bash脚本的执行结构之if选择执行结构:

   if语句:格式:

         if: if 命令; then 命令; [ elif 命令; then 命令; ]... [ else 命令; ] fi   ---用fi作结尾,与if遥相呼应


   if执行结构包括单分支、双分支以及多分支执行结构:

    if语句的单分支结构:

      if 命令; then 命令; fi

      注意:是否会执行then后面的命令,取决于if后面的命令的执行状态返回值;

            1.如果返回值为真,则执行后面的命令;

            2.如果返回值为假,则不执行后面的命令;

        书写形式两种:

          if CONDITION ; then 

            STATEMENT

            ...

           fi 

           或

           if CONDITION 

           then 

            STATEMENT

            ...

           fi 


    if语句的双分支结构:

      if 命令; then 命令;  elif 命令; fi

      注意:是否会执行then或else后面的命令,取决于if后面的命令的执行状态返回值;

            1.如果返回值为真,则执行then后面的命令;

            2.如果返回值为假,则执行else后面的命令;

        书写形式两种:

          if CONDITION ; then 

            STATEMENT

            ...

          else

            STATEMENT

            ...

          fi 

           或

           if CONDITION 

           then 

            STATEMENT

            ...

           else

            STATEMENT

            ...

           fi 


    if语句的多分支结构:

      if 命令; then 命令; [ elif 命令; then 命令; ]... [ else 命令; ] 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

                   STATEMENGT

                   ...

                 fi

               else

                 STATEMENT

                 ...

               fi

             else

               STATEMENT

               ...

             fi


例:写一个脚本,判断某个用户的的默认登录shell是否为/bin/bash,如果不是,显示其登录shell;


#!/bin/bash

#

USERNAME=$(cut -d: -f1 /etc/shadow | sort -R | head -1)

USERSHELL=$(egrep  "^$USERNAME\>"" /etc/passwd | cut -d: -f7)

if [ $"USERSHELL" == "/bin/bash" ] ; then

  echo "${USERNAME}'s login is /bin/bash"

else 

  echo "${USERNAME}'s login is ${USERSHELL}"

fi


//最后要撤销已经定义过的变量,否则会造成内存空间的浪费

unset USERNAME USERSHELL



bash脚本编程之用户交互使用:

  位置参数变量:

    $0:命令的本身,对于脚本而言,就是该脚本的路径;

    $1,$2,...$N:脚本后面通过命令行给脚本传递命令行参数;

      【N>9时,引用该位置变量时需要加花括号{},即${10}】


  特殊变量:

    $@:给出的所有位置参数的列表,当使用双引号引用时,每个参数作为单独的字符串存在;

    $*:给出的所有位置参数的列表,当使用双引号引用时,整个参数列表被当做一个字符串;

    $#:表示除了$0之外传递参数的个数;


{shift:shift: shift [n]

       移位位置参数。

       重命名位置参数 $N+1、$N+2 ... 到 $1、$2 ...  如果没有给定 N,

       则假设为1.

       退出状态:

       返回成功,除非 N 为负或者大于 $#。

   具体含义:在脚本中添加shift命令后,$0指文件的路径基名,无法被替换,shift无法对$0进行移位,只能相应的对后面的$1进行移位操作,shift命令操作之后(默认是移动1位),原来的$0保持不变,原来的$1被移位即消除没有了,原来的$2变成了进行shift命令操作后的$1,原来的$3变成了进行shift命令操作后的$2,后续位置元素同样道理;当(shift 2)命令操作即移位2位,原来的$3变成了移位操作后的$1}



  read命令:

    read  [-a 数组]  [-p 提示符] [-t 超时] [-u 文件描述符] [名称 ...]

     -a array:定义索引数组;

     -p prompt:给用户输出提示信息;

     -t timeout:用户输入的超时时间;

     name:变量或数组的名称;如果省略此内容,bash会将read读到的信息保存到一个内置的名为REPLY变量中


    注意: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 argumengts."

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 has created successfully and it's passwd has changed to it's username."

else

if id $2 &> dev/null ;then

echo "User $2 has existed."

   fi

fi

elif [ $1 == '-d' ];then

if id $2 &> /dev/null;then

userdel $2 $> /dev/null

echo "User $2 deleted finihed."

else

echo "User $2 does not exists yet."

    fi

else

echo "Usage: $(basename $0) -a USERNAME | -d USERNAME"

exit 6

fi



和用户交互使用read命令:

#!/bin/bash

#

if [ $# -ne 2 ];then

echo "Make sure provide TWO argumengts."

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 has created successfully and it's passwd has changed to it's username."

else

if id $USERNAME &> dev/null ;then

echo "User $USERNAME has existed."

    fi

fi

elif [ $1 == '-d' ];then

read -p "Please input a username for deleting: " USERNAME

read -p -t5 "Are you sure to delete $USERNAME? Input 'yes/no' to be next." CHOICE

[ -z $CHOICE ] && CHOICE='no'


if [ $CHOICE == 'yes' ];then

if id $USERNAME &> /dev/null;then

userdel $USERNAME $> /dev/null

echo "User $USERNAME deleted finihed."

else

echo "User $USERNAME does not exists yet."

    fi

    else [ $CHOICE == 'no' ];then

    echo "$USERNAME is not deleted."

    fi

else

echo "Usage: $(basename $0) {-a | -d}"

exit 6

fi