条件测试:


        界定程序执行环境;(本质是判定程序是否执行)

        (1) 根据运行的命令的状态结果判定;    
            例如 id root &>/dev/null 等    
       
        (2) 测试表达式    
            test EXPRESSION    
            [ EXPRESSION ]    
            ` EXPRESSION `(建议多多使用此[[]],测试表达式和[]必须有空格)

        整数测试:隐含着做数值大小比较,所以不要给变量引用加引用;    
            $A -gt $B:是否大于;是则为“真”,否则为“假”;    
            $A -ge $B: 是否大于等于;    
            $A -lt $B:是否小于;    
            $A -le $B: 是否小于等于;    
            $A -eq $B: 是否等于;    
            $A -ne $B:是否不等于;

        字符串测试:ASCII数值越大,字符比较时其值越大;    
            "$A" > "$B":是否大于;    
            "$A" < "$B":是否小于;    
            "$A" == "$B":是否等于;    
            "$A" != "$B":是否不等于;    
            -z "$A":是否为空;空则为“真”,否则为“假”    
            -n "$A":是否不空;不空则“真”,空则为“假”

            如果首字符相同则比较第二个字符以此类推    
            注意:应该使用` EXPRESSION `

        文件测试:测试文件的存在性以及属性;    
            -e $file: 是否存在;存在则为“真”,否则为“假”;    
            -a $file: 同上;    
            -f $file:文件是否存在且为普通文件;    
            -d $file:文件是否存在且为目录;    
            -h $file:是否存在且为符号链接文件;    
            -L $file: 同上    
            -b $file:是否存在且为块设备文件;    
            -c $file:是否存在且为字符设备文件;    
            -S $file:是否存在且为套接字文件;    
            -p $file: 是否存在且为管道文件;

            -r $file: 当前用户对文件是否拥有读权限;    
            -w $file:当前用户对文件是否拥有写权限;    
            -x $file:当前用户对文件是否拥有执行权限;

            -u $file:文件是否拥有SUID权限;    
            -g $file:文件是否拥有SGID权限;    
            -k $file:文件是否拥有sticky权限;

            -O $file: 当前用户是否为指定文件的属主;    
            -G $file: 当前用户是否为指定文件的属组;

            双目操作符:    
            $file1 -nt $file2: file1是否新于file2, file1的最近一次的修改时间戳是否晚于file2             的;    
            $file1 -ot $file2: file1是否旧于file2, file1的最近一次的修改时间戳是否早于file2             的;    
            $file1 -ef $file2:file1与file2是否指向了同一个inode;测试二者是否为同一个文件             的硬链接;

bash之条件判断(选择执行):      
        if/then, case

        if CONDITION; then      
            if-true-分支(condition判定为真执行该段)      
        fi

        if CONDITION; then      
            if-true-分支      
        else      
            if-false-分支(condition判定为假执行该段)      
        fi

        ! CONDITION: 取反


    练习:写一个脚本      
        如果某路径不存在,则将其创建为目录;否则显示其存在,并显示内容类型;      

#!/bin/bash       
#       
filename="/tmp/x/y/z/testdir"       
if [ -e $filename ]; then          ##判定变量filename的变量值是否存在       
   echo "$filename exists."       
   file $filename                      ##存在则执行以上两行操作       
else                                           ##不存在执行如下操作       
   mkdir -p $filename       
   fi

练习:写一个脚本,完成如下功能;      
        判断给定的两个数值,孰大孰小;      
            给定数值的方法:脚本参数,命令交互;

#!/bin/bash      
#       
read -p "Plz enter two integer: " -t 10 num1 num2   
##与用户以交互方式 赋值变量num1 变量num2
if [ -z "$num1" ]; then                      
   echo "Plz give two integers."       
   exit 1                       ##判定第一个参数是否为空 是则提示并退出脚本      
fi
if [ -z "$num2" ]; then      
   echo "Plz give tow integers."       
   exit 1                       ##判定第一个参数是否为空 是则提示并退出脚本       
fi
if [ $num1 -ge $num2 ]; then    ##判定变量num1的变量值是否大于变量num2的变量值      
   echo "Max: $num1, Min: $num2."         ##变量num1大则执行此命令                                                                      
   else       
   echo "Max: $num2, Min: $num1."         ##变量num1小则执行此命令       
fi

多分支的if语句:      
    单分支:      
        if CONDITION; then      
            if-true-分支      
        fi

    双分支:      
        if CONDITION; then      
            if-true-分支    ()   
        else      
            if-false-分支      
        fi

    多分支:用于需要对多种情况判定是否执行时使用      
        if CONDITION1; then      
            if-CONDITION1-true-分支      
        elif CONDTION2; then      
            if-CONDITIO2-true-分支      
        ...      
        else      
            if-ALL-false-分支      
        fi

        示例:通过脚本参数传递一个文件路径给脚本,判断其类型;(文件只会符合一个判定条件)      

#!/bin/bash       
 #       
if [ $# -lt 1 ]; then       
    echo "Usage: $0 <path>"       
    exit 1       
fi                ##以上检测至少要有一个参数传递给脚本 否则脚本结束
if [ -f $1 ]; then                               
     echo "Rgular file."      ##传递的第一个参数是存在而且是普通文件       
elif [ -d $1 ]; then       
   echo "Directory."          ##传递的第一个参数是存在而且是目录文件       
elif [ -h $1 ]; then       
   echo "Symbolic link."     ##传递的第一个参数是存在而且是符号链接文件       
elif [ -b $1 ]; then       
   echo "Block special."      ##传递的第一个参数是存在而且是块文件       
elif [ -c $1 ]; then       
   echo "Charactoer special."   ##传递的第一个参数是存在而且是字符文件       
elif [ -S $1 ]; then       
   echo "Socket file."          ##传递的第一个参数是存在而且是套接字文件       
else       
   echo "file not exist or unknown type."    ##以上判定都不是则执行此命令       
fi

        

     示例:脚本可接受四个参数      
            start: 创建文件/var/lock/subsys/SCRIPT_NAME      
            stop: 删除此文件      
            restart: 删除此文件并重新创建      
            status: 如果文件存在,显示为"running",否则,显示为"stopped"

            basename命令:      
                取得路径的基名;

#!/bin/bash      
#       
prog=$(basename $0)               ##取得脚本路径的基名赋值给变量prog       
lockfile="/var/lock/subsys/$prog"          ##生产新的路径赋值给变量lockfile       
#echo $lockfile
if [ $# -lt 1 ]; then      
   echo "Usage: $prog start|stop|restart|status"       
   exit 1       
fi             ##判定必须有至少一个参数传递给脚本
if [ "$1" == "start" ]; then      
   if [ -f $lockfile ]; then       
      echo "$prog is started yet."            
      ##判定传递来的参数是start 且$lockfile是普通文件则显示脚本is started yet       
   else       
      touch $lockfile && echo "Starting $prog ok..." || echo "Starting $prog failed..."
      ##判定传递来的参数是start 且$lockfile不存在,则创建$lockfile文件创建成功后显示Starting $prog ok.,如果创建失败则显示启动失败      
fi       
elif [ "$1" == 'stop' ]; then       
   if [ -f $lockfile ]; then       
     rm -f $lockfile && echo "Stop $prog ok...." || echo "Stop $prog failed..."
     ##判定传递来的参数是stop且$lockfile是普通文件则强制删除$lockfile删除成功后显示Stop $prog ok....",如果删除失败则显示停止失败
   else      
   echo "$prog is stopped yet."
##判定传递来的参数是stop且$lockfile不存在则显示$prog(取变量值 )is stopped yet    
fi       
elif [ "$1" == 'restart' ]; then       
   if [ -f $lockfile ]; then       
      rm -f $lockfile && touch $lockfile && echo "Restarting $porg ok..."
      ##判定传递来的参数是restart且$lockfile是普通文件则强制删除$lockfile删除成功后创建新的$lockfile,创建成功后显示Restarting $porg ok      
   else       
     touch $lockfile && echo "$prog is stopped, Starting $prog ok...."
     ##判定传递来的参数是restart且$lockfile不存在则创建新的$lockfile,创建成功后显示$prog is stopped, Starting $prog ok              
fi      
elif [ "$1" == 'status' ]; then       
   if [ -f $lockfile ]; then       
     echo "Running..."
     ##判定传递来的参数是status且$lockfile是普通文件则显示正在运行      
   else       
     echo "Stopped..."
     ##判定传递来的参数是status且$lockfile不存在则显示已经停止      
fi       
else       
    echo "Usage: $prog start|stop|restart|sttus"       
    exit 1
    ##判定如传递来的参数不是start|stop|restart|sttus,则提示Usage: $prog start|stop|restart|sttus,然后错误结束脚本      
fi


case语句      
    简洁版多分支if语句;               
    使用场景:判断某变量的值是否为多种情形中的一种时使用;

    语法:      
        case $VARIABLE in      
        PATTERN1)      
            分支1      
            ;;                 ##判定$VARIABLE符合PATTERN1则执行分支1命令

        PATTERN2)      
            分支2      
            ;;                ##判定$VARIABLE符合PATTERN2则执行分支2命令      
        PATTERN3)      
            分支3      
            ;;                ##判定$VARIABLE符合PATTERN3则执行分支3命令      
        ...      
        *)      
            分支n      
            ;;                ##判定$VARIABLE符合PATTERNn则执行分支n命令      
        esac

        PATTERN可使用glob模式的通配符:      
            *: 任意长度的任意字符;      
            ?: 任意单个字符;      
            []: 指定范围内的任意单个字符;      
            a|b: 多选1;

        示例:提示键入任意一个字符;判断其类型;      

#!/bin/bash       
#       
read -p "Plz enter a character: " char   
##提示输入一个字符 用交互方式复制给变量char
case $char in      
[a-z])                   ##输入的为一个字母则显示为字母       
    echo "A character."       
    ;;       
[0-9])       
    echo "A digit."      ##输入的为一个数字则显示为数字       
    ;;       
*)       
     echo "A special character."      ##如果以上匹配不到,且输入的是任意长度的任意字符则显示为特殊字符       
    ;;       
esac

          

      示例:脚本可接受四个参数      
            start: 创建文件/var/lock/subsys/SCRIPT_NAME      
            stop: 删除此文件      
            restart: 删除此文件并重新创建      
            status: 如果文件存在,显示为"running",否则,显示为"stopped"

#!/bin/bash      
#       
prog=$(basename $0)       
lockfile="/var/lock/subsys/$prog"       
#echo $lockfile
if [ $# -lt 1 ]; then      
   echo "Usage: $prog start|stop|restart|status"       
   exit 1       
fi
case $1 in      
   start)       
   if [ -f $lockfile ]; then       
      echo "$prog is started yet."
##判定传递来的参数是start 且$lockfile是普通文件则显示脚本is started yet      
   else       
      touch $lockfile && echo "Starting $prog ok..." || echo "Starting $prog failed..."
   ##判定传递来的参数是start 且$lockfile不存在,则创建$lockfile文件创建成功后显示Starting $prog ok.,如果创建失败则显示启动失败      
fi       
;;       
   stop)       
   if [ -f $lockfile ]; then       
     rm -f $lockfile && echo "Stop $prog ok...." || echo "Stop $prog failed..."
   ##判定传递来的参数是stop且$lockfile是普通文件则强制删除$lockfile删除成功后显示Stop $prog ok....",如果删除失败则显示停止失败      
   else       
      echo "$prog is stopped yet."
   ##判定传递来的参数是stop且$lockfile不存在则显示$prog(取变量值 )is stopped yet      
   fi       
;;       
   restart)       
   if [ -f $lockfile ]; then       
      rm -f $lockfile && touch $lockfile && echo "Restarting $porg ok..."
   ##判定传递来的参数是restart且$lockfile是普通文件则强制删除$lockfile删除成功后创建新的$lockfile,创建成功后显示Restarting $porg ok      
   else       
      touch $lockfile && echo "$prog is stopped, Starting $prog ok...."
   ##判定传递来的参数是restart且$lockfile不存在则创建新的$lockfile,创建成功后显示$prog is stopped, Starting $prog ok      
   fi       
;;       
   status)       
   if [ -f $lockfile ]; then       
      echo "Running..."       
      ##判定传递来的参数是status且$lockfile是普通文件则显示正在运行      
   else       
      echo "Stopped..."
   ##判定传递来的参数是status且$lockfile不存在则显示已经停止      
   fi       
;;       
   *)       
      echo "Usage: $prog start|stop|restart|sttus"       
      exit 1
      ##判定如传递来的参数不是start|stop|restart|sttus,则提示Usage: $prog start|stop|restart|sttus,然后错误结束脚本      
esac


循环语句:


        for, while, until

        循环:将循环体代码执行0、1或多次;    
            进入条件:进入循环的条件;    
            退出条件:循环终止的条件;    
       
        格式:    
        for VARIABLE in LIST; do    
            循环体    
        done

        LIST:是由一个或多个空格或换行符分隔开的字符串组成;    
            把列表的每个字符串逐个赋值给VARIABLE表示的变量;

            for username in user1 user2 user3; do    
                循环体    
            done

            进入条件:列表非空;    
            退出条件:列表遍历结束;

            添加10个用户,user1-user10;

               

 #!/bin/bash    
 #     
 for username in user1 user2 user3 user4 user5; do          ##循环进入标记列表仍有可以赋值,结束条件为列表参数全部赋值过     
   if id $username &> /dev/null; then     
       echo "$username exists."     
   else     
       useradd $username     
       echo "Add user $username finished."     
   fi     
done

            LIST的生成方法:    
                (1) 整数列表    
                    (a) {start..end}    
                    (b) $(seq [start `step` end)    
                (2) 直接给出列表  例如for username in user1 user2 user3 user4 user5    
                (3) glob (bash通配)例如 for file in /etc/f*    
                (4) 命令生成          for file in $(ls /mnt)

                示例:数值列表    

                    #!/bin/bash     
                    #     
                    for i in {1..10}; do              ##直接给出列表     
                        if id user$i &> /dev/null; then     
                        echo "user$i exists."     
                        else     
                        useradd user$i     
                            echo "Add user user$i finished."     
                        fi     
                    done

                示例:glob    

                    #!/bin/bash     
                    #     
                    for filename in /var/log/*; do         ##轮值为/var/log下的所有文件     
                        file $filename     
                    done

                示例:命令生成列表    

                    #!/bin/bash     
                    #     
                    for username in $(cut -d: -f1 /etc/passwd); do          ##命令引用取列表为系统中的所有用户     
                        echo "$username primary group: $(id -n -g $username)."     
                    done

                示例:求100以内所以正整数之和;    

            #!/bin/bash                 
            #                 
            declare -i sum=0
            for i in {1..100}; do         变量i的变量值轮1到100                   
               sum=$[$sum+$i]         ##将变量sum的变量值加上变量i的变量值所得值再重新赋值变量sum    
            done
            echo $sum

示例:显示/etc目录下所有普通文件列表,而后统计一共有多少个文件;

        #!/bin/bash            
        #             
        declare -i count=0                  ##定义计数器 整型变量count
        for file in /etc/*; do              ##使用通配方法生产/etc文件目录下的文件列表                if [ -f $file ]; then                                     
             let count++                ##当是普通文件时计数器变量count自己+1                     echo "$count $file"                 
             fi             
        done
        echo "Total: $count files."

示例:写一个脚本实现如下功能;    
            获取当前主机的主机名;    
                如果当前主机的主机名为空,或者为localhost,则将其修改为www.magedu.com    
           

#!/bin/bash                 
#                 
hostname=$(hostname)            ##命令引用取得命令执行结果赋值给变量hostname
if [ -z "$hostname" -o "$hostname" == "localhost" ]; then   ##或表达式组合运用              hostname www.magedu.com                 
fi

       

        练习:写一个脚本,打印九九乘法表;

            循环嵌套

            1X1=1    
            1X2=2 2X2=4    
            1X3=3 2X3=6 3X3=9

            #!/bin/bash    
            #     
            for j in {1..9}; do     
                for i in $(seq 1 $j); do   ##双循环嵌套使用 保证被乘数不得大于乘数     
                    echo -n -e "${i}X${j}=$[$i*$j]\t"        
                done     
                echo     
            done

循环语句:for, while, until

        while循环:

            while CONDTION; do    
                循环体    
            done

            进入条件:当CONDITION为“真”;    
            退出条件:当CONDITION为“假”;

            while CONDITION; do    
                循环体    
                控制变量的修正表达式 (如果没有修正变量可能会死循环)    
            done

            示例:求100以内所有正整数之和;

                #!/bin/bash                    
                #                     
                declare -i sum=0                     
                declare -i i=1
                while [ $i -le 100 ]; do                        
                   let sum+=$i                         
                   let i++                     
                done
                echo "Sum: $sum."

            练习:分别求100以内所有奇数之和,及所有偶数之和;

#!/bin/bash
#
declare -i sum1=0
declare -i sum2=0
declare -i i=0
while [ $i -le 100 ]; do
        if [ $[${i}%2] -eq 0 ]; then
          let sum1+=$i
        else
          let sum2+=$i
        fi
        let i++
done
echo "qishu sum $sum2"
echo "oushu sum $sum1"

            示例:打印九九乘法表    
               

#!/bin/bash                     
#                     
declare -i i=1                     
declare -i j=1
while [ $j -le 9 ]; do                       
    while [ $i -le $j ]; do                             
      echo -e -n "${i}X${j}=$[$i*$j]\t"                             
      let i++                         
    done                         
    echo                         
    let i=1                         
    let j++                     
done

        unitl循环:    
            until CONDITION; do    
                循环体    
                循环控制变量的修正表达式    
            done

            进入条件:当CONDITION为“假”时    
            退出条件:当CONDITION为“真”时

            示例:求100以内所有正整数之和    

                #!/bin/bash                     
                #                     
                declare -i sum=0                     
                declare -i i=1
                until [ $i -gt 100 ]; do                        
                   let sum+=$i                         
                   let i++                     
                done
                echo "Sum: $sum."

            练习1:分别求100以内所有偶数之和,以及所有奇数之和;

    

#!/bin/bash
#
declare -i sum1=0
declare -i sum2=0
declare -i i=0
until  [ $i -gt 100 ]; do
        if [ $[${i}%2] -eq 0 ]; then
          let sum1+=$i
        else
          let sum2+=$i
        fi
        let i++
done
echo "qishu sum $sum2"
echo "oushu sum $sum1"

            练习2:实现九九乘法表; 

#!/bin/bash
#
#!/bin/bash
#
declare -i i=1
declare -i j=1
until  [ $i -gt 9 ]; do
       until [ $j -gt $i ]; do
         echo -n "${j}x${i}=$[$j*$i] "
         let j++
       done
         let j=1
         let i++
        echo
done

   
            练习3:分别使用while和until循环实现添加10个用户:user1-user10;

#!/bin/bash
#
declare -i i=1
while [ $i -le 10 ]; do
        useradd user${i}
        let i++
done
#!/bin/bash
#
declare -i i=1
until [ $i -gt 10 ];do
         useradd user${i}
        let i++
done


        循环控制:    
            continue [n]:提前结束本轮循环,而直接进入下一轮;    
            break [n]:提前结束循环;

            while循环:    
                while CONDITION; do    
                    .......    
                    if CONDITION2; then    
                        break [n]    
                    fi    
                done

                while CONDITION; do    
                    ......    
                    if CONDITION2; then    
                        continue [n]    
                    fi    
                    ......    
                done

            示例:求100以内所有偶数之和;

                #!/bin/bash                    
                #                     
                declare -i sum=0                     
                declare -i i=0
                while [ $i -le 100 ]; do                        
                    let i++                         
                   if [ $[$i%2] -eq 1 ]; then                         
                      echo "$i is a odd."                             
                      continue                         
                   fi                         
                    let sum+=$i                     
                done
                echo "Sum: $sum."

        死循环:    
            while true; do    
                循环体    
                if CONDTION; then    
                    break    
                fi    
            done

            until false; do    
                循环体    
                if CONDITION; then    
                    break    
                fi    
            done

            示例:每隔3秒钟查看当前系统上是否有名为“gentoo”的用户登录;    
                如果某次查看gentoo登录了,则显示gentoo已经登录;    
                如果未登录,就显示仍然未来,并显示这是已经是第多少次查看了;

              

  #!/bin/bash                    
  #                     
  username=$1                     
  declare -i count=0
  while true; do                        
      if who | grep "^$username" &> /dev/null; then                             
          echo "$username is logged."                              
          break                       
      else                               
          let count++                             
          echo "$count $username is not login."                         
      fi                         
      sleep 3                     
      done


               

#!/bin/bash                     
#                     
declare -i count=0                     
username=$1
if [ $# -lt 1 ]; then                        
         echo "At lease one argument."                         
         exit 1                     
         fi
if ! id $username &> /dev/null; then                        
         echo "No such user."                         
         exit 2                     
         fi
until who | grep "^$username" &> /dev/null; do                        
       let count++                         
       echo "$count $username is not login."                         
       sleep 3                     
       done
echo "$username is logged on."

        while循环的特殊用法:    
            遍历文件的每一行:    
                while read VARIABLE; do    
                    循环体    
                done < /PATH/FROM/SOME_FILE

            示例:找出UID为偶数的所有用户,显示其用户名和ID号;    

                #!/bin/bash     
                #     
                while read line; do     
                    userid=$(echo $line | cut -d: -f3)     
                    if [ $[$userid%2] -eq 0 ]; then     
                        echo $line | cut -d: -f1,3     
                    fi     
                done < /etc/passwd

        for循环的特殊用法:    
            for ((expr1;expr2;expr3)); do    
                循环体    
            done

            expr1: 定义控制变量,并初始赋值;    
            expr2: 循环控制条件;    
                进入条件:控制条件为“真”    
                退出条件:控制条件为“假”    
            expr3: 修正控制变量

            示例:求100以内所有正整数之和;    

                #!/bin/bash                     
                #                     
                declare -i sum=0
                for ((i=1;i<=100;i++)); do                        
                  let sum+=$i                     
                done
                echo "Sum: $sum."

               

            练习1:打印九九乘法表;   

#!/bin/bash
#
for (( i=1;i<10;i++));do
        for (( j=1;j<=i;j++));do
            echo -n "${j}x$i=$[ $j*$i ] "
        done
        echo
done

 
            练习2:传递一个文本文件为参数给脚本,取出此文件的所有的偶数行给予显示,行前要显示行号;

#!/bin/bash
#
if [ $# -lt 1 ]; then
  echo " must ernter /path/to/somefile "
  exit 1
fi
j=$(wc -l $1 | cut -d" " -f1 )
if [ -f $1 ]; then
  for (( i=1;i<=j ;i++  ));do
        if [ $[${i}%2] -eq 0 ];then
          echo -n "$i  "
           head -$i $1 | tail -1
        fi
  done
fi