Bootstrap

shell脚本-语法

   shell脚本
    1.for循环
    Shell脚本的for循环结构和C语言很不一样,它类似于某些编程语言的foreach循环
    for循环有两种写法
    (1)for i in {a..z}
         do
             echo $i
         done
    (2)类C方式
       for(( i=0; i<100; i++ ))
       do
           echo $i
       done
    
    2.if条件判断
    if命令的参数组成一条子命令,如果该子命令的Exit Status 为0(表示真),则执行then后面的子命令,如果Exit Status非0(表示假)则执行elif(shell中的else if用elif表示)、else或者fi后面的子命令。if后面的子命令通常是测试命令,但也可以是其他命令。shell脚本中没有{}括号,所以用fi表示if语句块的结束

    关于参数列表:
    $0:相当于C语言main函数的argv[0]
    $1、$2..: 这些称为位置参数,相当于C语言main函数的argv[1]、argv[2]..
    $#:相当于C语言main的argc(注意,这里的#后面不表示注释
    $@:表示参数列表“$1”“$2”..,例如可以在for循环中的in后面
    $?:上一条命令的Exit Status
    $$:当前shell的进程号

    实例:求参数列表中的最大值、最小值
    程序
   [ $# -eq 0 ] && {
       echo "Usage $0 data1 .. datan"
       exit 1
   }
   max=$1
   min=$1
   for i in $@
      do
          if [ $max -lt $i ];then
              max=$i
          fi
          if [ $min -gt $i ];then
              main=$i
          fi
   done
   echo "max=$max,min=$min"

    2.while循环
     书写方法
     while [ 条件判断 ]
     do
             内容
     done
    3.函数
    shell中的函数被当做一个程序或小脚本, 当函数传参时,$0永远不被使用。
    shell函数定义中没有返回值也没有参数列表(函数体的左花括号和后面的命令之间必须有空格或换行,如果将最后一条命令和右花括号写在同一行,命令末尾必须有分号)
    shell脚本中的函数调用不写括号
    shell脚本中的函数必须先定义后调用,一般把函数调用都写在脚本的前面,把函数调用和其他命令写在脚本的最后(类似C语言中的main函数,这才是整个脚本实际开始执行命令的地方)
    shell函数没有参数列表,但shell中的函数就像是迷你脚本,调用函数时可以传任意个函数,在函数内同样是用$1 $2等变量来提取参数,函数中的位置参数相当于函数的局部变量,改变这些变量并不会影响函数外的$1 $2等变量。函数中可以用return命令返回,如果return后面跟一个数字则表示函数的Exit Status
    
    函数中定义的变量默认在本bash中全局有效,声明变量时加上local ,可使变量只在函数体内有效
    Shell脚本函数支持递归  

    实例:1.函数实现求最大、最小值
    myfunction()
   {
     max=$1
     min=$1
      for i in $@
          do
              if [ $max -lt $i ];then
                  max=$i
              fi
              if [ $min -gt $i ];then
                  min=$i
              fi
      done
      echo "max=$max,min=$min"
   }
    myfunction $@


    实例2.程序 .(){ . | . & }; .
    一个后台运行的递归函数,其内部不断创建子进程
   该程序可使电脑关机,且无法杀掉
    .是一个函数名

    set +x
    从此条语句以下不打印执行过程,只打印执行结果
    set -x
    从此条语句后,打印执行结果和执行过程

    4.数组
    shell支持一维数组(不支持多维数组),并且不限制数组的大小。类似C语言,数组原酸的下标由0开始编号。获取数组中的元素要利用下标,下标可以是整数或算术表达式,其值应大于或等于0
    定义数组:
    在shell中,用括号来表示数组,数组元素用“空格”符号分隔开。定义数组的一般形式为:array_name=(value1...valuen)
    可以不使用连续的下标,且下标的范围没有限制。
    读取数组元素值的一般形式:${array_name[index]}
    使用@或*可以获取数组中的所有元素:${array_name[*]}
   
    实例:将a到z存入数组,且打印下标和内容
      arr=()
      j=0
      for i in {a..z}
      do
        arr[$j]=$i
        let j++
    done
    j=0
     for i in ${arr[@]}
    do
        echo $i$j
    #print "%s" "$i$j"
        let j++
    done

    5.条件测试
    命令test或[可以测试一个条件是否成立,如果测试结果为真,则该命令的Exit Status为0,如果测试结果为假,则命令的Exit Status为1(与C语言逻辑正好相反)
    左方括号[是一个命令的名字,传给命令的各参数之间应该用空格隔开
    判断整数
    -eq     相等
    -ne     不相等
    -gt     大于
    -ge     大于等于
    -lt     小于
    -le     小于等于

    判断字符串
    ==     相等
    !=     不相等
    =      相等
    
    判断字符串为空     [ -z "字符串" ]
    判断字符串部位空   [ -n "字符串" ]
    判断文件为目录     [ -d 文件名 ]
    判断文件为普通文件 [ -f 文件名 ]

    带与、或、非的测试命令
    [ ! EXPR ]:EXPR可以是任意一种测试条件
    [ EXPR1 -a EXPR2 ]:EXPR1、EXPR2可以是任意一种测试条件
    [ EXPR1 -o EXPR2 ]:EXPR1、EXPR2可以是任意一种测试调价

    6.:是一个特殊的命令,称为空命令,该命令不做任何事,但Exit Status总是真的
   
    7.case/esac
    case命令可类比C语言的switch/case语句,esac表示case语句块的结束。C语言的case只能匹配整形或字符型常量表达式,而shell脚本的case可以匹配字符串和Wildcard,每个匹配分支可以有若干条命令,末尾以;;结束,执行时找到第一个匹配的分支并执行相应的命令,然后直接跳到esac之后,不需要像C语言一样用break跳出


    printf也是一条命令   格式 printf "打印内容"  "$变量"  
   
   实例:斐波那契数列

    (1)迭代的方法(方法一)
    first=1
    second=1
    last=1
   
    i=3
    while [ $i -le $1 ]
    do
        let last=first+second
        let first=second
        let second=last
        let i++
    done
    echo $last

    (2)迭代方法实现(方法二)
     arr=(1 1)
   
     i=0
   
     while [ $i -le $1 ]
    do
         let arr[$i+2]=arr[$i+1]+arr[$i]
         let i++
   done
 
    echo ${arr[@]}
    echo ${arr[$1-1]}

    (3)递归方法实现
    if [ $# -ne 1 ];then
        exit 1
    fi
      function fib(){
       local num=$1
       if [ $num -le 2 ];then
             echo 1
             return
        fi  
        local p=$((num-1))
        local pp=$((num-2))
        local first=`fib $pp`
        local second=`fib $p`
        echo "$first+$second" | bc
    }
    fib $1

    (4)简化版本递归实现
      function fib(){
           local num=$1
          [ $num -le 2 ] && {
             echo 1
            return
        }   
        echo " `fib $((num-1))`+`fib $((num-2))`" | bc

    实例:SHELL脚本读取文件,将文件内容按三个字符截取为一组,并且将小写字母转换成大写字母
      读取文件方法   cat file | while read line
      cut -c 按字符截取
      大小写替换  echo "abc" | tr '[a-z]' '[A-Z]'
      while read line
     do
        part1=`echo $line | cut -c 1-3`
        part2=`echo $line | cut -c 4-6 | tr '[a-z]' '[A-Z]'`
        part3=`echo $line | cut -c 7-9`
 
        echo $part3$part2$part1 >> file.res
     done <  file


    实例:脚本与信号关联 
    利用t rap命令
      function fun(){
        echo "hello world"
        return 0
     }  
     trap 'fun' 2
     while :
        do
            :
       done


    头文件引用方式,使用. 头文件文件名称或source 头文件名称或sh 头文件名称
;