您的位置:新葡亰496net > 电脑系统 > 新葡亰496netShell脚本语言,基本操作小结

新葡亰496netShell脚本语言,基本操作小结

发布时间:2019-10-22 05:07编辑:电脑系统浏览(190)

    1.echoif else fi命令

    #!/bin/bash
    echo hello;echo there
    filename=demo.sh
    if [ -e "$filename" ]; then 
        echo "$filename already exists!";cp $filename $filename.bak
    else
        echo "$filename does not exist!";
    fi;
    echo "File test complete!"
    

    运行结果(demo.sh不存在):

    hello
    there
    demo.sh does not exist!
    File test complete!
    

    需要注意的是filename=demo.sh等号两边是不能有空格的;if [ -e "$filename" ]中[]左右两侧都是有空格的。

       从事机顶盒开发以来,看到很多的Shell脚本,比如:开机启动脚本、系统升级脚本、软探针脚本、和系统编译脚本。这些脚本都是用shell语言开发,虽然在平时的需求开发和维护中会涉及到一定的脚本修改,但是一直没有系统的学习过shell语言。
    

    新葡亰496net 1

    shell脚本语句

      shell诞生于unix,是unix/linux交互的工具,单独地学习shell是没有意义的。

    2.shell基本操作

    所以本篇文章主要是记录学习shell过程中的笔记。同时也为巩固markdown语法,本篇笔记都是用markdown记录。

    第一个shell脚本

    #!/bin/bash
    echo "hello, world"
    

    运行程序可以作为解释器参数或者作为可执行程序

    bash test.sh
    
    chmod  x test.sh
    test.sh
    

    运算符符

    1. 运算符的使用 - * /

      1. expr是计算整数类型行的数据
      2. 运算符左右都要有空格
      3. ``和$()是取结果集

        1. 注意*必须要通过转义,不然会出错
        2. `与$()不但可以取整数运算的结果,还可以取shell命令的结果集,比如:result=ls`或者$(ls)
        3. result='expr num1 % num2'=num1/num2商...余数
          num=1
          num1=2
          num2=`expr $num   $num1`
          //num2=`expr $num * $num1`
          echo "${num2}"
          
        4. 可以用$((num1 num2))
    2. let关键字

      num1=1
      num2=2
      let num3=num1 num2
      echo "${num3}"
      
      • 可以用在 - * / % --
      1. --(都只能用在let里,不能在expr里使用)
      • 后缀
      num1=1
      let num2=num1  
      printf "num1=%sn" "${num1}"
      printf "num2=%sn" "${num2}"//num2=1,num=2
      
      • 前缀
      num1=1
      let num2=  num1
      printf "num1=%sn" "${num1}"
      printf "num2=%sn" "${num2}"//num2=2,num=2
      
      • 后缀--
      num1=1
      let num2=num--
      printf "num1=%sn" "${num1}"
      printf "num2=%sn" "${num2}"//num2=1,num=0
      
      • 前缀 --
      num1=1
      let num2=--num
      printf "num1=%sn" "${num1}"
      printf "num2=%sn" "${num2}"//num2=0,num=0
      
      • =
      num1=1
      let num2 =num1
      printf "num2=%sn" "${num2}"//num2=3
      

    3 . 整数之间的关系运算符

    • > < >= <= != ==
    • -gt -ge -lt -le -eq -nq

      在关系运算符中,运算结果是一个逻辑,如果关系表达式成立,逻辑值为1,否则为0。
    • 除!=,==都要用转义
    • !=可以用转义也可以不用转义
    • =,=,==,==(由编译器决定,mac支持=,=)
      num1=1 num2=2 num3=`expr $num1 > $num2` echo "${num3}"

      shell需要依赖其它程序才能完成大部分工作,这或许是他的缺陷,但是它不容置疑的长处是:简洁的脚本语言标记方式而且比C语言编写的程序执行更快、更有效率。

    2.1 变量大于,等于,小于

    #!/bin/bash
    a=1
    if [ $a -gt 0 ]; then
        echo "greater than zero!"
    else
        echo "no more than zero!"
    fi
    if [[ $a -lt 0 ]]; then
        echo "less than zero!"
    else
        echo "no less than zero!"
    fi
    if [[ a -eq 1 ]]; then
        echo "equal to 1!"
    else
        echo "not equal to 1!"
    fi
    

    -gt表示大于;-lt表示小于;-eq表示等于。运行结果为:

    greater than zero!
    no less than zero!
    equal to 1!
    

    shell脚本语言

    变量

    命名

    name="huruji"
    

    需要注意的是变量名与等号之间不能有空格。

    使用

    echo $name
    echo ${name}
    

    使用在变量名前添加$即可,{}表示这个变量名的边界。

    只读变量

    name="huruji"
    readonly name
    

    使用readonly可以将变量定义为只读变量,只读变量不能再次赋值

    删除变量

    name="huruji"
    unset name
    

    使用unset删除变量,之后不能再使用。

    关系运算符语句

    1. if语句:如果一个数大于5,然后输出这个数,否则如果这个数小于5,然后说明这个数小于5

      if []
      then
          语句体
      elif
      then
          语句体
      else
          语句体
      fi
      注意点1. []左右两边都要有空格
            2. 关系运算符用-gt 等表示
      
      printf "请输入一个数:"
      read num
      if [ $num -gt 5 ]
      then 
          echo "${num}"
      elif [ $num -lt 5 ]
      then 
          printf "%s小于5n" "${num}"
      else
          printf "这个数等于5" 
      fi
      
      • 总结:
        1. else可以没有,如果有else,必须放在最后面,else下面没有then
        2. elif可以没有,必须要放在if与else中间的位置
        3. if语句只能执行一个分支
        4. if结束的标志fi
          //输入两个整数求最大值输出
      printf "请输入两个整数n"
      read num1
      read num2
      if [ $num1 -gt $num2 ]
      then 
          printf "最大值为%sn" "${num1}"
      else
          printf "最大值为%sn" "${num2}"
      fi
      
    2. 字符串运算符

      • =:判断字符串是否相等
      • !=:判断字符串是否不等
      string1="hello"
      string2="hello"
      if [ $string1 == $string2 ]
      then 
          echo "equal"
      else
          echo "not equal"
      fi
      
      • -z:zero:判断字符串是否为空或是不存在
      string=""
      if [ -z $string ]
      then 
          echo "字符串为空"
      else
          echo "字符串不为空"
      fi
      
    3. 文件运算符

      • -d:判断是否为目录文件
      • -f:判断是否为普通文件
      • -r: 判断是否可读
      • -w:判断是否可写
      • -x:判断是否可执行
      • -e:exsit:判断是否存在

    //练习:判断~/share是否存在,如果不存在就创建这个文件,如果存在就提示已存在的信息。

    1. case语句

      case 变量 in
      条件1)
          语句体1
      ;;
      条件2)
          语句体2
      ;;
      esac
      
      printf "请输入一个数n"
      read num
      case $num in
      1)
          printf "是1" "${num}"
      ;;
      2)
          printf "是2" "${num}"
      ;;
      *)
          printf "啥都不是"
      ;;
      esac
      
      • 注意点
      • 结束标志必须是esac
      • 值1)和值2)可以相同
      • 如果值1)和值2)都不满足,就会来到*)
      • *)可以不写,但要写就要写在最后
      • 每一个分支结束都有一个;;
    2. 数组

      • 数组的初始化
        • 一个变量一个变量进行初始化
          • array1[0]=8
          • array1[1]=9
          • 一个一个变量进行初始化,可以间隔赋值,还可以不从位置0开始。比如aray1[1]=2,array1[5]=5
        • 集体赋值
          • array=(1 2 3 4 hello)(可以是不同数据类型)
      • 数组元素的访问
        • ${数组名[下标]}
      • 遍历数组里所有的元素
        • ${数组名[*]||[@]}
      a=(1 2 3 4 hello)
      echo "${a[2]}"
      echo "${a[@]}"
      
    3. while循环

      while []
      do
          语句体
      done
      
      sum=0
      i=1
      while [ $i -le 100 ]
      do
          let sum=sum i;
          let i  ;
      done
      echo "sum=${sum}"
      
    4. 参数

      • ./XX.sh
        • $0:代表执行文件./XX.sh
        • $1:代表执行的第一个参数
        • $2:代表执行的第二个参数
        • $n:代表执行的第二个参数
        • $#:代表执行的参数个数,不包括命令本身
    5. 逻辑运算符

      • && 并且:如果事件1成立并且事件2也成立,整个事件才成立。否则不成立。
      • || 或者:两个事件只要有一个成立,整个事件就成立。
      • ! :对事件取反
      案例1
      printf "请输入一个数n"
      read num 
      #if [ $((num%5)) -eq 0 ] && [ $((num%3)) -eq 0 ]
      if [[ $((num%5)) -eq 0 && $((num%3)) -eq 0 ]]
      #if [ $((num%5)) -eq 0 -a $((num%3)) -eq 0 ](用了-a,-o就可以只用一个[])
      then
          echo "YES"
      else
          echo "NO"
      fi
      

      //判断闰年(能被4整除,且不被100整除,且可以被400整除)

      案例2
      printf "请输入一个年份n"
      read num
      if [[ $((num%4)) == 0 && $((num0)) != 0 ]] || [ $((num@0)) == 0 ]
      then 
          printf "是闰年"
      else 
          printf "不是闰年"
      fi
      
    6. for循环

      • 格式:
      for 变量 in 参数列表
      do
          语句体
      done
      
      • 遍历打印当前目录下的子目录与子文件
      value=`ls`
      for file in $value
      do 
          echo "${file}"
      done
      

    10.break:是跳出整个循环

    • 当碰到break时,直接跳
      出循环,break下面的语句不会被执行。
    • break只跳出最近的一层循环

      //计算和时只要大于54就退出

        count=0
        while [ $count -le 1 ]
        do 
            i=1
            sum=0
            while [ $i -le 100 ]
            do 
                if [ $sum -gt 54 ]
                then 
                    break
                fi
                let sum =i
                let i  
            done
            printf "sum=%sn" "${sum}"
            printf "i=%sn" "${i}"
            let count  
        done
      
    1. continue

      • 当碰到continue时,跳出本层循环当前的一次循环,continue下面的语句不会被执行
      • continue只能存在于循环中。
        //1-20和,跳过3的倍数
      i=1
      sum=0
      while [ $i -le 20 ]
      do
          if [ $((i)) == 3 ]
          then 
              let i  
              continue
          fi
          let sum =i
          let i  
      done
      echo "sum=${sum}"
      分析:i=3时,if条件成立,执行continue,那么continue下面的语句就不会被执行,继续返回到while判断的语句看条件是否成立,如果成立继续执行
      
    2. 死循环

      while:
      do
          语句体
      done
      
    3. shell函数

      • 函数调用之前必须要有相应的函数
      • 什么时候用到函数
        • 执行的功能类似
        • 根据实际需求,需要时就用
      • shell函数定义格式
      function 函数名()
      {
      }
      
      • 调用函数:直接写函数名
      • 函数参数传递
      function test()
      {
          echo "$0"
          echo "$1"
          echo "$2"
          echo "${10}"
          echo "hello world"
      }
      test 1 2 3 4 5 6 7 8 9 100
      分析:1. 当参数作为shell函数参数传递时,当在函数里面接受n>=10个参数时,要加上${n}
      2. $0不是test,而是shell文件本身
      3. 函数里面的$1与外面的与外面的$1不同,但是函数里面的$0与函数外面的$0相同。
      
      • 函数返回值
      sum()
      {
          num1=$1
          num2=$2
          let value=num1 num2
          return $value
      }
      sum 1 2
      echo "sun=$?"
      sum 2 3
      echo "sun=$?"//结果为sum=3nsum=5n
      分析:1. **函数如果是return出来的结果,我们用$?接受,$?是接受最后运行的一次脚本**
      2. 如果return后面的值大于255,那么函数运行完后用$?接受,$?=value%6。
      3. 怎么接受return出来比255大的值,解决之道:使用echo num 返回出来,函数外使用变量接收,value=`函数名`,从而对value进行操作。
      
      • shell函数里面可以内嵌创建函数

        a()
        {
            b()
            {
                echo "aaa"
            }
        }
        a
        b
        b在什么情况下会被使用,先要调用a,因为a里有b的实现
        
        • 条件函数
        a()
        {   
            value=1
            if [ $value == 1 ]
            then
                b()
                {
                    echo "aaa"
                }
            else
                c()
                {
                    echo "ccc"
                }
        }
        a
        b
        函数b和函数c在什么情况下可以调用,先运行函数a,因为a中有函数b和函数c的实现,在if语句条件成立时实现函数b的定义;else其他情况实现函数c的定义。
        
      • 总结:

        • function关键字可以不写
        • shell函数可以有return,也可以没有
        • 如果return出来的结果必须要用$?接收
        • 如果是用echo保存的结果集,必须要用value=·test·接收
        test()
        

      {
      echo 555
      }
      value=test
      echo "test函数返回值为${value}"
      //习题:求1-100偶数和

    sum=0
    i=1
    while [ $i -le 100 ]
    do
        if [ `expr $i % 2` -eq 0 ]
        then
            let sum=sum i
        fi
        let i  
    done
    echo "sum=${sum}"
    

    //打印99乘法表

    i=1
    j=1
    while [ $i -le 9 ]
    do
        j=1
        while [ $j -le $i ]
        do
            t=`expr $i * $j` 
            printf "%s*%s=%s " "$i" "$j" "$t"
            let j  
        done
        printf "n"
        let i  
    done
    

    //输入两个整数,再输入一个 -*/运算符,根据运算符,计算两个数结果,用case

    printf "输入两个整数"
    read i
    read j
    printf "输入一个运算符"
    read s
    case $s in
    " ")
        printf "%s %s=%sn" "${i}" "${j}" "$((i j))"
    ;;
    "-")
        printf "%s-%s=%sn" "${i}" "${j}" "$((i-j))"
    ;;
    "*")
        printf "%s*%s=%sn" "${i}" "${j}" "$((i*j))"
    ;;
    "/")
        printf "%s %s=%sn" "${i}" "${j}" "$((i/j))"
    ;;
    esac    
    

    //打印

       *
      ***
     *****
    *******
    
    printf "请输入一个数n"
    read s
    i=1
    j=1
    while [ $i -le $s ]
    do
        j=1
        while [ $j -le $((s-i)) ]
        do 
            printf " "
        let j  
        done
        k=1
        while [ $k -le $((2*i-1)) ] 
        do 
            printf "*"
        let k  
        done
        printf "n"
        let i  
    done
    

    //脚本编写小练习:做一个sh 1.sh

    1. 判断是否有参数,参数是否为1
    2. 判断文件是否存在
    3. 如果存在,判断是否是普通文件
    4. 如果是普通文件,修改权限
    5. 运行
    6. 让这个命令在全局有效
      • chmod 777 XX.sh
      • mv XX.sh mysh
      • sudo cp mysh /bin
    7. 附加:判断是否为.sh文件是再进行下一步
    value="$1"
    lengh=${#value}
    value1=${value:$((lengh-3)):3}
    if [ $# -eq 0 ]
    then 
        echo "what do you want to do?"
    elif [ $# -eq 1 ]
    then
        if [ -e $1 ]
        then 
            if [ -f $1 ]
            then
            if [ $value1 == ".sh" ]
                then
                    chmod 777 $1
                    ./$1
                else 
                    printf "no .shn"
                fi
            else
                echo "no such files"
            fi
        else 
            echo "no such files or directory"
        fi
    else 
        echo "too much arguements"
    fi
    

      shell本身是一个用C语言编写的程序,它是用户使用unix/linux的桥梁,用户的大部分工作都是通过shell完成的,shell既是一种命令语言,又是一种程序设计语言。

    2.2 三目运算符(?:)

    # ? is 3 operator
    b=10
    ((t=b<20?6:4)) # t = 6
    echo "t=$t"
    # variable in () is a part region variable
    (b=20;echo "b = $b") # b = 20
    echo "b = $b" # b = 10
    

    和C,java等语言类似,shell中的?:也是三目运算符。()表示一个建立局部作用域,可以暂时屏蔽全局变量。上式的运行结果为:

    t=6
    b = 20
    b = 10
    

    1、什么是shell脚本语言?

    脚本语言是像剧本一样教计算机办某个事情的语言。

    脚本语言其实就是短小的、用来让计算机自动化完成一系列工作的程序,这类程序可以用文本编辑器修改

    不需要编译,通常解释运行。

    字符串

    name="huruji"
    
    echo "my name is $name"
    

    字符串可以使用单引号和双引号,单引号中不能包含单引号,即使转义单引号也不次那个,双引号则可以,双引号也可以使用字符串。

    拼接

    name="huruji"
    hello="my name is ${name}"
    

    获取字符串长度

    str="huruji"
    echo ${#str} #6
    

    提取子字符串

    str="huruji"
    echo ${str:2:3}
    

    从字符串的第二个字符开始提取3个字符,输出ruj

    查找

    str="huruji"
    echo `expr index "$str" u`
    

    此时输出2,因为此时第一个字符位置从1开始

    今日小结

    昨天刚接触脚本的时候抱着和其他人一样的感觉走,只是听说过脚本这个名词(游戏脚本现在好像十分流行)却不知道具体实现的功能与作用。用法与熟悉的C语言几乎完全不同,各类操作操碎了我的心。直到下午,亲爱的苍老师叫我们做了一个小练习,自己编写了一个类似sh作用的脚本直接运行.sh文件。让我醍醐灌顶,原来还可以这么用!不过我说的不是脚本的用法,而是苍老师编写程序时思路的用法。原谅我的词穷,这种东西只可意会不可言传。在那种思想的领导下,编写程序时思路比以前升级了1/3,速度比以前提高了1/3,如果将这种思路与方法熟练运用。自己的编程能力应该可以从中了玄冥神掌半死不活的张无忌升级成练了九阳神功第九重。

    1. 作为命令语言,它交互式地解释和执行用户输入的命令。
    2. 作为设计语言,它定义了各种变量和参数,并提供了许多在高级语言中才具有的控制结构:包括循环和分支。

    2.3 数组

    2、运行shell脚本的两个方法

    chmod  x ./XXX.sh    chmod后有空格
    ./XXX.sh
    
    /bin/sh XXX.sh
    

    数组

    定义

    names=("huruji" "greywind" "xie")
    echo ${names[0]}
    echo ${names[2]}
    

    读取

    echo ${names[2]}
    echo ${names[@]}
    

    如上例子,使用@可以获取数组中的所有元素

    获取长度

    length=${#names[@]}
    length=${#names[*]}
    

    $小结

    1. 现在假使有函数
    test()
    {
        value1=$1
        value2=$2
    }
    test year(=$1) mouth(=$2)
    输出结果为$?
    
    1. 假如现在判断的是执行文件后参数的个数
    ./XX.sh year mouth
    year=$1
    mouth=$2
    

      shell有两种执行命令的方式:

    2.3.1 数组创建
    # () create an array
    arr=(1 2 3 5 6)
    echo "arr[3] = ${arr[3]}"
    

    输出:

    arr[3] = 5
    

    3、shell变量

    定义变量时,变量名不加$,如:

    your_name="runoob.com"
    

    使用定义过的变量时,只要在变量名前面加上$符号即可,如:

    your_name="qinjx"
    echo ${your_name}
    

    Shell参数传递

    执行Shell脚本的时候,可以向脚本传递参数,在Shell中获取这些参数的格式为$n,即$1,$2.......,

    echo "第一个参数是:$1"
    echo "第一个参数是:$2"
    echo "第一个参数是:$3"
    

    运行

    chmod  x test.sh
    test.sh 12 13 14
    

    则此时输出:

    第一个参数是:12
    第一个参数是:13
    第一个参数是:14
    

    此外,还有其他几个特殊字符来处理参数

    • $#:传递脚本的参数个数
    • $*:显示所有的参数
    • $$:脚本当前运行的进程ID号
    • $!:后台运行的最后一个进程的ID号
    • $@:返回所有参数
    • $-:显示Shell的使用的当前选项
    • $?:退出的状态,0表示没有错误,其他则表示有错误

        交互式:解释执行用户的命令,用户输入一条命令,shell就解释执行一条。

    2.3.2 数组长度
    # get the length of array
    echo "length of arr is ${#arr[*]}" # 5
    echo "length of arr is ${#arr[@]}" # 5
    

    输出:

    length of arr is 5
    length of arr is 5
    

    只读变量

    readonly myUrl
    myUrl="www.baidu.com"
    

    运算

    算数运算
    原生bash不支持简单的数学运算,可以借助于其他命令来完成,例如awk和expr,其中expr最常用。expr是一款表达式计算工具,使用它能完成表达式的求值操作。

    val=`expr 2   2`
    echo $val
    

    需要注意的是运算符两边需要空格,且使用的是反引号。
    算术运算符包括: - × / % = == !=

    关系运算
    关系运算只支持数字,不支持字符串,除非字符串的值是数字。

    a=12
    b=13
    if [ $a -eq $b ]
        then
        echo "相等"
    else
        echo "不等"
    fi
    
    • -eq:是否相等
    • -ne:是否不等
    • -gt:大于
    • -lt:小于
    • -ge:大于等于
    • -le:小于等于

    布尔运算

    • !:非
    • -o:或
    • -a:与

    逻辑运算符

    • &&:逻辑与
    • ||:逻辑或

    字符串运算符

    • =:相等 [ $a = $b ]
    • !=:不等 [ $a 新葡亰496netShell脚本语言,基本操作小结。!= $b ]
    • -z:字符串长度是否为0,为0返回true [ -z $a ]
    • -n:字符串长度是否为0,不为0返回true [ -n $a ]
    • str:字符串是否为空,不为空返回true [ $a ]

    文件测试运算符
    用于检测Unix文件的各种属性。

    • -b:检测文件是否为块设备文件 [ -b $file ]
    • -c:检测文件是否为字符设备文件 [ -c $file ]
    • -d:检测文件是否为目录 [ -d $file ]
    • -f:检测文件是否为普通文件 [ -f $file ]
    • -g:检测文件是否设置了SGID位 [ -g $file ]
    • -k:检测文件是否设置了粘着位 [ -k $file ]
    • -p:检测文件是否是有名管道 [ -p $file ]
    • -u:检测文件是否设置了SUID位 [ -u $file ]
    • -r:检测文件是否可读 [ -r $file ]
    • -w:检测文件是否可写 [ -w $file ]
    • -x:检测文件是否可执行 [ -x $file ]
    • -s:检测文件大小是否大于0 [ -s $file ]
    • -e:检测文件是否存在 [ -e $file ]
    file="/home/greywind/Desktop/learnShell/test.sh"
    
    if [ -e $file ]
        then
        echo "文件存在"
    else
        echo "文件不存在"
    fi
    
    if [ -r $file ]
        then
        echo "可读"
    else
        echo "不可读"
    fi
    
    if [ -w $file ]
        then
        echo "可写"
    else
        echo "不可写"
    fi
    
    
    if [ -x $file ]
        then
        echo "可执行"
    else
        echo "不可执行"
    fi
    
    if [ -d $file ]
        then
        echo "是目录"
    else
        echo "不是目录"
    fi
    
    if [ -f $file ]
        then
        echo "是普通文件"
    else
        echo "不是普通文件"
    fi
    

        批处理:用户事先写一个shell脚本,其中有很多条命令,让shell一次把这些命令执行完,而不必一条一条地敲命令。

    2.3.3 输出数组元素
    # get all content of array
    echo "arr:${arr[*]}" # 1 2 3 5 6
    # or
    echo "arr:${arr[@]}" # 1 2 3 5 6
    

    输出:

    arr:1 2 3 5 6
    arr:1 2 3 5 6
    

    删除变量

    unset myUrl
    

    echo

    echo在显示输出的时候可以省略双引号,使用read命令可以从标准输入中读取一行并赋值给变量

    read name
    echo your name is $name
    

    换行使用转义n,不换行使用c
    此外使用 > 可以将echo结果写入指定文件,这个文件不存在会自动创建

    echo "it is a test" > "/home/greywind/Desktop/learnShell/hello"
    

    使用反引号可以显示命令执行的结果,如date、history、pwd

    echo `pwd`
    echo `date`
    

      shell的种类很多:bash、sh、ash、csh、ksh等,bash是linux标准的shell,bash完全兼容sh。

    2.3.4 修改数组元素
    # assign a new element to an array
    arr[1]=100
    echo "arr:${arr[@]}" # 1 100 3 5 6
    # if assign index if out of bound,then auto create a new element of array
    arr[10]=20 # 1 100 3 5 6 20
    echo "arr:${arr[@]}"
    

    输出:

    arr:1 100 3 5 6
    arr:1 100 3 5 6 20
    

    注意如果赋值索引超出数组长度,相当于是给数组末尾增加一个新元素。

    变量类型

    1、局部变量 :局部变量在脚本或命令中定义,仅在当前shell实例中有效,其他shell启动程序不能访问变量

    2、环境变量 :所有的程序,包括shell启动的程序,都能访问环境变量,有些程序需要环境变量来保证其正常运行。必要的时候shell脚本也可以定义环境变量

    3、shell变量 :shell变量是由shell程序设置的特殊变量,shell变量中有一部风是环境变量,有一部分是局部变量,这些变量保证了shell的正常运行

    printf

    Shell中的输出命令printf类似于C语言中的printf(),
    语法格式:

    printf format-string [arguments...]
    
    printf "%-10s %-8s %-4sn" 姓名 性别 体重kg  
    printf "%-10s %-8s %-4.2fn" 郭靖 男 66.1234 
    printf "%-10s %-8s %-4.2fn" 杨过 男 48.6543 
    printf "%-10s %-8s %-4.2fn" 郭芙 女 47.9876 
    

      运行shell脚本有两种方式:

    2.3.5 删除数组元素
    # delete the element of array
    unset arr[1] # delete the arr[1],1 3 5 6 20
    echo "arr:${arr[*]}" # 1 3 5 6 20
    # clear the whole array
    unset arr 
    echo "${#arr[@]}" # length 0
    

    输出:

    arr:1 3 5 6 20
    0
    

    unset 如果跟上数组的索引,是删除该位置的数组元素;如果直接跟数组名,相当于是清空数组。

    4、shell字符串

    字符串可以使用单引号也可以使用双引号,也可以不使用引号

    强烈建议使用双引号

    test

    test命令用于检查某个条件是否成立,可以进行数值、字符、文件三方面的测试

    a=100
    b=200
    if test a == b
        then
        echo "相等"
    else
        echo "不等"
    fi
    

        作为可执行程序      ./test.sh

    2.3.6 数组切片
    arr=(1 2 4 10)
    # slice of array
    # ${array_name[*]:start:length},return is a string
    echo "${arr[@]:0:3}" # 1 2 4
    # assignment
    arr1=(${arr[*]:1:2}) # arr1:2 4
    echo "${#arr1[@]}"
    echo "arr1:${arr1[@]}"
    

    输出:

    1 2 4
    2
    arr1:2 4
    

    获取字符串长度

    string="adcg"
    echo ${#string}
    

    多了个#

    流程控制

    if

    a=100
    b=200
    if test $a -eq $b
        then
        echo "相等"
    else
        echo "不等"
    fi
    
    a=100
    b=200
    if test $a -eq $b
        then
        echo "相等"
    elif test $a -gt $b
        then
        echo "a大于b"
    elif test $a -lt $b
        then
        echo "a小于b"
    fi
    

    for

    for num in 1 2 3 4
    do
        echo ${num}
    done
    
    num=10
    for((i=1;i<10;i  ));
    do
        ((num=num 10))
    done
    echo $num
    

    while

    num=1
    while [ $num -lt 100 ]
    do
        ((num  ))
    done
    
    echo $num
    

    无限循环

    while:
    do
          command
    done
    
    while true
    do
          command
    done
    
    for (( ; ; ))
    

    until

    until condition
    do
          command
    done
    

    case

    case 值 in
    模式1)
        command1
        command2
        ...
        commandN
        ;;
    模式2)
        command1
        command2
        ...
        commandN
        ;;
    esac
    

    需要注意的是与其他语言不同Shell使用;;表示break,另外没有一个匹配则使用*捕获该值

    echo "输入1 2 3任意一个数字"
    read num
    case $num in
        1)echo "输入了1"
    ;;
        2)echo "输入了2"
    ;;
        3)echo "输入了3"
    ;;
        *)echo "输入的值不是1 2 3"
    ;;
    esac
    

    与其他语言类似,循环可以使用break和continue跳出

        作为参数解释器      /bin/sh   test.sh

    2.3.7 数组元素替换
    # replace
    # ${array_name[@]/origin_element/new_element}
    # this operation doesn't change the origin array
    # and will return a string that seperated by space
    echo "${arr1[*]/2/20}" # 20 4,arr1:2 4
    arr1=(${arr1[*]/4/40}) # arr1:2 40
    echo "${arr1[*]}" # 2 40
    

    输出:

    20 4
    2 40
    

    提取字符串

    string="runoob is a great site"
    scho ${string 1:4} 输出uoo ,从0开始算
    

    函数

    函数定义
    用户自定义函数可以使用或者不使用function关键字,同时指定了return值则返回这个值,如果没有return语句则以最后一条运行结果作为返回值。

    function first(){
        echo "hello world"
    }
    
    first(){
        echo "hello world"
    }
    

    调用函数直接使用这个函数名即可

    first
    

    函数参数
    调用函数可以传入参数,函数内部使用$n获取传入的参数,类似于运行程序使用时获取使用的参数,不过需要注意的是两位数以上应该使用{}告诉shell边界例如${12}、${20}

    function add(){
        num=0;
        for((i=1;i<=$#;i  ));
        do
            num=`expr $i   $num`
        done
        return $num
    }
    add 1 2 3 4 5
    a=$?
    
    echo $a
    

    函数本身是一个命令,所以只能通过$?来获得这个返回值

      shell支持自定义变量

    2.4 文件操作

    # file operation
    if [ ! -w 't.txt' ]; then
        touch t.txt
    fi
    echo 'test text' > t.txt 
    cp t.{txt,back} # cp t.txt to t.back
    filename="/home/lyrichu/login"
    if [ -r $filename ] # if file is readable
        then 
        echo "$filename is readable!"
    else
        echo "$filename is not readable!"
    fi
    
    if [ -e $filename ]
        then
        echo "$filename exists!"
    else
        echo "$filename doesn't exist!"
    fi 
    

    输出:

    /home/lyrichu/login is not readable!
    /home/lyrichu/login doesn't exist!
    

    上面的代码首先检查t.txt文件是否可写,如果不可写,则重新创建一个文件;然后向t.txt文件写入字符串'test text';接着复制t.txt文件到t.back文件;
    然后判断/home/lyrichu/login文件是否可读以及是否存在。

    5、shell数组

    shell只支持一维数组

    输入输出重定向

    在上文的例子中可以使用 > 可以将echo结果写入指定文件,这就是一种输出重定向,重定向主要有以下:

    • command > file:输出重定向至文件file
    • command < file:输入重定向至文件file
    • command >> file:输出以追加的方式重定向至文件file
    • n > file:将文件描述符为n的文件重定向至文件file
    • n >> file:将文件描述符为 n 的文件以追加的方式重定向到文件file
    • n >& m:将输出文件 m 和 n 合并
    • n <& m:将输入文件 m 和 n 合并
    • << tag:将开始标记 tag 和结束标记 tag 之间的内容作为输入

    将whoami命令输出保存到user文件中

    who > "./user"
    

    使用cat命令就可以看到内容已经保存了,如果不想覆盖文件的内容那么就使用追加的方式即可。

    who >> "./user"
    

      定义变量

    2.5 {}创建一个代码块

    # {} create a code block
    a=10;echo "a=$a"
    { a=20; } # a = 20
    echo "a=$a" # a = 20
    

    输出:

    a=10
    a=20
    

    定义数组

    用括号来表示数组,数组元素用“空格”符号分割开来,定义数组的一般形式为:

    array_name=(value0 value1 value2 value3)
    

    Shell文件包含

    Shell脚本可以包含外部脚本,可以很方便的封装一些公用的代码作为一个独立的文件,包含的语法格式如下:

    . filename
    # 或
    source filename
    

    如:
    test1.sh

    echo "hello world"
    

    test.sh

    source ./test1.sh
    
    echo "hello"
    

        定义变量时,变量名不加美元符号($):

    2.6 expr 计算表达式的值

    val=`expr $a   $b` # a = 20,b = 10
    echo "a   b = $val" # a   b = 30
    
    val=`expr $a * $b` # * means multiply,a*b = 10*20 = 200
    echo "a*b=$val"
    
    # divide
    val=`expr $a / $b` # 20/10 = 2
    echo "a / b = $val"
    
    # mod
    val=`expr $a % 9` # 20 % 9 = 2
    echo "$a % 9 = $val" # 20 % 9 = 2
    

    输出:

    a   b = 30
    a*b=200
    a / b = 2
    20 % 9 = 2
    

    expr可以计算shell表达式的值,上式分别计算了 ,*,/,%运算,注意乘法需要使用*转义。

    读取数组

    valuen=${array_name[1]}
    

    使用@符号可以获取数组中的所有元素,例如:

    echo ${array_name[@]}
    

    取得数组元素的个数

    length=${#array_name[@]
    

    取得数组单个元素的长度

    length=${#array_name[1]}
    

          var iablename="value"

    2.7 逻辑运算符

    if [ $a == $b ]
    then echo "a == b!"
    fi
    if [ $a != $b ] 
        then 
        echo "a != b" 
    fi 
    
    # && logit and
    if [[ $a -gt 10 && $b -lt 20 ]]
        then
        echo "$a > 10 and $b < 20!"
    else
        echo "bad condition!"
    fi
    # || logit or 
    if [[ $a -gt 15 || $b -gt 15 ]]
        then
        echo "a > 15 or b > 15"
    else
        echo "a<=15 and b<=15"
    fi 
    

    输出:

    a != b
    20 > 10 and 10 < 20!
    a > 15 or b > 15
    

    == 用于比较数字相等;!=用于比较数字不等。&&表示shell中的逻辑与;||表示shell中的逻辑或运算。

    6、shell传递参数

    脚本内获取参数的格式为:$n,n代表一个数字,$0代表文件名,、$1代表参数1,$2代表参数2。

    输出不存在的参数时结果为空

    • $#新葡亰496net, 传递到脚本的参数个数

    • $* 以一个单字符串显示所有脚本传递的参数

    • $$ 脚本运行的当前进程号

        注意,变量名和等号之间不能有空格,这可能和你熟悉的所有编程语言都不一样。

    2.8 字符串操作

    #!/bin/bash
    s1="abhsgd"
    # 获取字符串长度
    echo "length of s1:" ${#s1}
    #提取子字符串
    # ${string:position},在string中,从position位置开始提取子字符串
    echo ${s1:2} # hsgd
    # ${string:position:length},string中,从position位置开始提取长度为length的子字符串
    echo ${s1:2:2} # hs 
    # ${string#substring},从string的开头, 删除最短匹配substring的子串,返回删除子串之后的字符串
    echo ${s1#ab} #hsgd
    # ${string##substring},从string的开头, 删除最长匹配substring的子串
    echo ${s1##abh} # sgd
    # ${string%substring},从string的结尾, 删除最短匹配substring的子串
    echo ${s1%gd} # absh
    # ${string%%substring},从string的结尾, 删除最长匹配substring的子串
    echo ${s1%%hsgd} # ab
    # ${string/substring/replacement},使用replacement,来代替第一个匹配的substring
    echo ${s1/hs/HS} # abHSgd
    # ${string//substring/replacement},使用replacement, 代替所有匹配的substring
    s2=ahjhjhhshdg
    echo ${s2//h/H} # aHjHjHHsHdg
    # ${string/#substring/replacement},如果string的前缀匹配substring, 那么就用replacement来代替匹配到的substring
    echo ${s2/#ahj/AHJ} # AHJhjhhshdg
    # ${string/%substring/replacement},如果string的后缀匹配substring, 那么就用replacement来代替匹配到的substring
    echo ${s2/%shdg/SHDG} # ahjhjhhSHDG
    ## 注:上面replacement可以是正则表达式,比如:
    s3=/home/lyrichu/demo.txt 
    # 得到文件名
    echo ${s3##*/} #demo.txt 
    # 得到目录名
    echo ${s3%/*} # /home/lyrichu
    

    输出:

    length of s1: 6
    hsgd
    hs
    hsgd
    sgd
    abhs
    ab
    abHSgd
    aHjHjHHsHdg
    AHJhjhhshdg
    ahjhjhhSHDG
    demo.txt
    /home/lyrichu
    

    7、shell基本运算符

    无法把基本运算符结果false或者true当做字符串赋值给变量

    进行四则运算时=两边不用空格, 两边一定要空格,四则运算一定要用双括号,比如

    num=(($num 1))
    

      变量名的命名遵循如下规则:

    2.9 控制流

    算数运算符

    格式:expr `a b`

    • 表达式和运算符之间要有空格,例如2 2是不对的,必须写成2 2

    • 完整的表达式要被``包含,注意这个字符不是常用的单引号

    1. 首个字符必须是字母
    2. 中间不能有空格,可以使用下划线(_)
    3. 不能使用标点符号
    4. 不能使用bash里的关键字
    2.9.1 if语句
    a=10
    b=20
    if [ $a == $b ]
        then
        echo "$a == $b !"
    elif [[ $a -gt $b ]]; then
        echo "$a > $b!"
    elif [[ $a -lt $b ]]; then
        echo "$a < $b!"
    else
        echo "Error!"
    fi
    
    # test command
    if test $a -lt $b
        then 
        echo "$a < $b!"
    else
        echo "$a >= $b!"
    fi 
    

    输出:

    10 < 20!
    10 < 20!
    

    其中test命令用来判断一条语句的真假。

    关系运算符

    关系运算符只支持数字,不支持字符串,除非字符串的值是数字

    假定a=10,b=20

    运算符 说明 举例
    -eq 检测两个数是否相等,相等返回true [$a -eq $b] 返回false
    -ne 检测两个数是否相等,不相等返回true [$a -ne $b]返回true
    -gt 检测左边的数是否大于右边,如果是,返回true [$a -gt $b]返回false
    -lt 检测左边的数是否小于右边,如果是,返回true [$a -gt $b]返回true
    -ge 检测左边的数是否大于等于右边的,如果是,则返回 true。 [ $a -ge $b ] 返回 false。
    -le 检测左边的数是否小于等于右边的,如果是,则返回 true。 [ $a -le $b ] 返回 true。

      使用变量

    2.9.2 for 语句
    # for loop
    for i in 1 2 3 4
    do
        echo "The value is $i"
    done
    
    # for loop of string
    for s in This is a string
    do
        echo "$s"
    done
    

    输出:

    The value is 1
    The value is 2
    The value is 3
    The value is 4
    This
    is
    a
    string
    

    布尔运算符

    • ! 非运算
    • -0或运算
    • -a与运算

      使用一个定义过的变量,只要在变量名前面加上美元符号($)即可

    2.9.3 while 循环
    #while loop
    i=1
    while(( $i<5 ))
    do
        echo "$i"
        let "i  "
    done
    
    echo "Press CTRL D to exit!"
    echo -n "Who is the most beautiful girl?"
    while read MAN
    do
        echo "Yes! $MAN is really beautiful!"
    done 
    

    输出:

    1
    2
    3
    4
    Press CTRL D to exit!
    Who is the most beautiful girl?yp
    Yes! yp is really beautiful!
    

    逻辑运算符

    &&与运算

    ||或运算

    your_name="mazhiyuan"
    echo $your_name
    echo ${your_name}
    
    2.9.4 case 语句
    # case mode
    echo "Please input a number between 1 to 4!"
    read input
    case input in
        1) echo "Your choice is 1!"
        ;;
        2) echo "Your choice is 2!"
        ;;
        3) echo "Your choice is 3!"
        ;;
        4) echo "Your choice is 4!"
        ;;
        *) echo "You don't choose a number between 1 and 4!"
        ;;
    esac 
    
    ## break 
    while :
    do
        echo "PLease input a number between 1 and 5!"
        read n 
        case $n in 
            1|2|3|4|5) echo "Your input number is $n!"
            ;;
            *) echo "Your input is not between 1 and 5!"
                break
            ;;
        esac 
    done
    

    输出:

    Please input a number between 1 to 4!
    3
    Your choice is 3!
    PLease input a number between 1 and 5!
    5
    Your input number is 5!
    PLease input a number between 1 and 5!
    10
    Your input is not between 1 and 5!
    

    字符串运算符

    运算符 说明 举例
    = 检测两个字符串是否相等,相等返回 true。 [ $a = $b ] 返回 false。
    != 检测两个字符串是否相等,不相等返回 true。 [ $a != $b ] 返回 true。
    -z 检测字符串长度是否为0,为0返回 true。 [ -z $a ] 返回 false。
    -n 检测字符串长度是否为0,不为0返回 true。 [ -n $a ] 返回 true。
    str 检测字符串是否为空,不为空返回 true。 [ $a ] 返回 true。

      推荐使用给所有变量加上花括号;这是一个好的变成习惯。

    2.10 函数

    文件测试运算符

    运算符 说明 举例
    -s file 检测文件是否为空(文件大小是否大于0),不为空返回 true。 [ -s $file ] 返回 true。
    -e file 检测文件(包括目录)是否存在,如果是,则返回 true。 [ -e $file ] 返回 true。

      已经定义的变量可以被重新定义。

    2.10.1 一个简单的没有参数,没有返回值的函数
    func1(){ # fuction that does not have parameters
        echo "This is my first function!"
    }
    # call function
    func1
    

    输出:

    This is my first function!
    

    8、shell流程控制

      只读变量

    2.10.2 带有返回值的函数
    func2(){ # function with return
        echo "This is function that has return!"
        return 1
    }
    # use $? to get the function return value
    func2
    echo "The return value of func2 is $?"
    

    输出:

    This is function that has return!
    The return value of func2 is 1
    

    在末尾使用return关键字即可以返回一个值,使用$?来获取函数的返回值。

    if语句

    if语句

    if ····
    then 
        ·····
        ·····
    fi
    

    if else语句

    if ····
    then
        ····
        ····
    else 
        ····
    fi
    

    if else-if else

    if ·····
    then
        ······
    elif ····· 
    then 
        ·····
    else
        ·····
    fi
    

      使用readonly命令可以将变量定义为只读变量,只读变量的值不能被修改。

    函数传递参数,获取参数总数,参数值以及第i个参数
    # input parameters of function
    # $1,$2,... to the first n parameter
    func3(){
        n=$# # get the total number of parameters
        echo "There are total $n parameters of func3!"
        echo "The first parameter is:$1"
        echo "The second parameter is $2"
        echo "The tenth parameter is ${10}"
        echo "The all parameters as string is:$*"
    }
    func3 1 2 3 4 5 6 7 8 9 10 11 12
    

    输出:

    There are total 12 parameters of func3!
    The first parameter is:1
    The second parameter is 2
    The tenth parameter is 10
    The all parameters as string is:1 2 3 4 5 6 7 8 9 10 11 12
    

    for循环

    for循环格式为:

    for var in items items2 item3 .... itemsN
    do
      command1
      command2
      ··
      commandN
    done
    

      删除变量

    3.一些简单的shell 实例

    while语句

    while循环用于不断执行一系列命令,也用于从输入文件中读取数据,命令通常为测试条件,其格式为:

    while condition
    do
        command
    done
    

    如果while condition涉及四则运算,需要使用双括号

    单引号(‘’):括起来的字符作为普通字符

    双引号(“”):括起来的字符,除 “$”, “”, “`”和“``”保留其特殊功能外,其余仍作为普通字符

    反引号(``):括起来的字串被解释为命令,shell首先执行该命令,并一他的标准输出结果例

      使用unset命令可以删除变量,变量被删除后不能再次使用;unset命令不能删除只读变量。

    3.1 计算3个数的最大值

    # calculate the max value of 8,4,5
    a=5
    b=4
    c=8
    i=$a
    
    if [[ $i -lt $b ]]
        then
        i=$b
    fi
    
    if [[ $i -lt $c ]]
        then
        i=$c
    fi
    echo "The max value of $a,$b,$c is $i"
    

    输出:

    The max value of 5,4,8 is 8
    

    9、shell函数

      变量类型

    3.2 随机猜数

    #!/bin/bash
    # random generate a number between 1 and 3, and let you to
    # guess the number's value,if you are right,then echo "You guess right!"
    # else echo "You guess wrong!"
    # use while to play the game,input "quit" to quit the game
    # $RANDOM generate a number between 0 and 32767
    while :
    do
        r=$RANDOM
        r=`expr $r % 3   1` # between 1 and 3
        echo "Please input a number between 1 and 10(enter quit to quit the game):"
        read g
        if [[ $g = "quit" ]]
            then
            break
        elif [[ $g == $r ]]; then
            echo "You guess right!"
        else
            echo "You guess wrong!"
        fi
    done
    

    输出:

    Please input a number between 1 and 10(enter quit to quit the game):
    2
    You guess right!
    Please input a number between 1 and 10(enter quit to quit the game):
    3
    You guess right!
    Please input a number between 1 and 10(enter quit to quit the game):
    3
    You guess wrong!
    Please input a number between 1 and 10(enter quit to quit the game):
    quit
    

    无参函数

    shell中函数的定义格式如下:

    [ function ] funname [()]
    {
        action;
        [return int;]
    }
    
    • 可以带function fun()定义,也可以直接fun()定义,不带任何参数
    • 参数返回,可以显示加,return返回,如果不加,将以最后一条命令运行结果,作为返回值。
    #!/bin/bash
    demoFun(){
        echo "这是我的第一个 shell 函数!"
    }
    echo "-----函数开始执行-----"
    demoFun
    echo "-----函数执行完毕-----"
    
    #!/bin/bash
    funWithReturn(){
        echo "这个函数会对输入的两个数字进行相加运算..."
        echo "输入第一个数字: "
        read aNum
        echo "输入第二个数字: "
        read anotherNum
        echo "两个数字分别为 $aNum 和 $anotherNum !"
        return $(($aNum $anotherNum))
    }
    funWithReturn
    echo "输入的两个数字之和为 $? !"
    
    • 函数返回值在调用后通过$?来获取
    • 所有函数在使用前必须定义,这意味着必须将函数放在脚本开始部分,直至shell解释器首次发现它时,才可以使用,调用函数仅使用其函数名即可

      运行shell时,会同时存在三种变量: 

    3.3 求小于100的所有偶数的和

    #!/bin/bash
    # sum the even number that less than 100
    i=2
    s=0
    while [[ $i -lt 100 ]]; do
        s=`expr $s   $i`
        i=`expr $i   2`
    done
    echo "The even number that less than 100's sum is $s"
    

    输出:

    The even number that less than 100's sum is 2450
    

    有参函数

    在shell中,调用函数时可以向其传递参数,,在函数内部,通过$n的形式来获取参数的值,例如:$1表示第一个参数

    #!/bin/bash
    funWithParam(){
        echo "第一个参数为 $1 !"
        echo "第二个参数为 $2 !"
        echo "第十个参数为 $10 !"
        echo "第十个参数为 ${10} !"
        echo "第十一个参数为 ${11} !"
        echo "参数总数有 $# 个!"
        echo "作为一个字符串输出所有参数 $* !"
    }
    funWithParam 1 2 3 4 5 6 7 8 9 34 73
    
    • 注意,$10不能获取第十个参数,获取第十个参数需要${10}
    参数处理 说明
    $# 传递到脚本的参数个数
    $* 以一个单字符串显示所有向脚本传递的参数
    $$ 脚本运行的当前进程ID号
    $! 后台运行的最后一个进程的ID号
    $@ 与$*相同,但是使用时加引号,并在引号中返回每个参数。
    $- 显示Shell使用的当前选项,与set命令功能相同。
    $? 显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。

    局部变量

    3.4 输出星号(*)金字塔

    #!/bin/bash
    # output the pyramid of stars
    for i in 4 3 2 1 0
    do
        j=$i 
        while [[ $j -gt 0 ]]
        do
            echo -n " "
            let "j--"
        done
        j=`expr 9 - 2 * $i`
        while [[ $j -gt 0 ]]
        do
            echo -n "*"
            let "j--"
        done
        j=$i 
        while [[ $j -gt 0 ]]
        do
            echo -n " "
            let "j--"
        done
        echo ""
    done
    

    输出:

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

    10、shell文件包含

    和其他语言一样,shell也可以包含外部脚本,这样可以很方便的封装一些公用的代码作为一个独立文件

    语法如下:

    . filename   # 注意点号(.)和文件名中间有一空格
    
    或
    
    source filename
    

    举例:

    test1.sh

    #!/bin/bash
    url="http://www.runoob.com"
    

    test2.sh

    #!/bin/bash
    #使用 . 号来引用test1.sh 文件
    . ./test1.sh
    # 或者使用以下包含文件代码
    # source ./test1.sh
    echo "菜鸟教程官网地址:$url"
    

    结果为:

    $ chmod  x test2.sh 
    $ ./test2.sh 
    
    • 被包含的文件test1.sh不需要可执行权限

      局部变量在脚本或命令中定义,仅在当前shell实例中有效,其它shell启动的程序不能访问局部变量。

    Reference

    1. linux shell 字符串操作(长度,查找,替换)详解
    2. linux shell 数组建立及使用技巧
    3. (实验楼)高级 bash 脚本编程指南

    环境变量

      所有的程序包括shell启动的程序,都能访问环境变量,有些程序需要环境变量来保证其正常运行,必要的时候shell脚本可以定义环境变量。

    shell变量

      shell变量是由shell程序设置的特殊变量。shell变量中有一部分是环境变量,有一部分是局部变量,这些变量保证了shell的正常运行。

    变量名只能包含字母、数字、下划线,因为某些包含其他字符的变量有特殊含义,这样的变量被称为特殊变量。

     

    变量

    含义

    $0 当前脚本的文件名
    $n 传递给脚本或函数的参数,n是一个数字,表示第几个参数
    $# 传递给脚本或函数的参数个数
    $* 传递给脚本或函数的所有参数
    $@ 传递给脚本或函数的所有参数,被双引号(“”)包含时,与$*稍有不同
    $? 上个命令的退出状态或函数的返回值
    $$ 当前shell进程ID,对于shell脚本,就是这些脚本所在的进程ID

              说明:

     "$*"会将所有的参数作为一个整体,以"$1 $2....$n"的形式输出所有参数

     "$@"会将各个参数分开,以“"$1" "$2"...."$n"”的形式输出所有参数

    转义字符 含义
    \ 反斜杠
    a 警报,响铃
    b 退格(删除键)
    f 换页(FF),将当前位置移到下页开头
    n 换行
    r 回车
    t 水平制表符(tab键) 
    v 垂直制表符

              说明:

     -e   对转义字符进行替换

     -E  禁止转义,默认也是不转义

      -n  禁止插入换行符

      命令替换是指shell可以先执行命令,将输出结果暂时保存,在适当的地方输出。  

        `command`

      注意是反引号

      变量替换是指根据变量的状态(是否为空、是否定义等)来改变它的值。

    可以使用的变量替换形式:

     

    形式 说明
    ${var} 变量本来的值
    ${var:-word} 如果变量 var 为空或已被删除(unset),那么返回 word,但不改变 var 的值。
    ${var:=word} 如果变量 var 为空或已被删除(unset),那么返回 word,并将 var 的值设置为 word。
    ${var:?message} 如果变量 var 为空或已被删除(unset),那么将消息 message 送到标准错误输出,可以用来检测变量 var 是否可以被正常赋值。
    若此替换出现在Shell脚本中,那么脚本将停止运行。
    ${var: word} 如果变量 var 被定义,那么返回 word,但不改变 var 的值。

      bash支持多种运算:算术运算符、关系运算符、字符串运算符、文件测试运算符等。原生的bash不支持简单的数学运算,但是可以通过其他命令来实现。expr是一款表达式计算工具,表达式和运算符之间有空格,完整的表达式要被反引号(`)包含。

      算术运算符 、-、*、/ 、% 、=、==、!= 条件表达式要放在方括号之间,并且要有空格。

      关系运算符(仅支持数字)

    运算符 说明 举例
    -eq 检测两个数是否相等,相等返回 true。 [ $a -eq $b ] 返回 true。
    -ne 检测两个数是否相等,不相等返回 true。 [ $a -ne $b ] 返回 true。
    -gt 检测左边的数是否大于右边的,如果是,则返回 true。 [ $a -gt $b ] 返回 false。
    -lt 检测左边的数是否小于右边的,如果是,则返回 true。 [ $a -lt $b ] 返回 true。
    -ge 检测左边的数是否大等于右边的,如果是,则返回 true。 [ $a -ge $b ] 返回 false。
    -le 检测左边的数是否小于等于右边的,如果是,则返回 true。 [ $a -le $b ] 返回 true。

      布尔运算符

    运算符 说明 举例
    ! 非运算,表达式为 true 则返回 false,否则返回 true。 [ ! false ] 返回 true。
    -o 或运算,有一个表达式为 true 则返回 true。 [ $a -lt 20 -o $b -gt 100 ] 返回 true。
    -a 与运算,两个表达式都为 true 才返回 true。 [ $a -lt 20 -a $b -gt 100 ] 返回 false。

      字符串运算符

    运算符 说明 举例
    = 检测两个字符串是否相等,相等返回 true。 [ $a = $b ] 返回 false。
    != 检测两个字符串是否相等,不相等返回 true。 [ $a != $b ] 返回 true。
    -z 检测字符串长度是否为0,为0返回 true。 [ -z $a ] 返回 false。
    -n 检测字符串长度是否为0,不为0返回 true。 [ -z $a ] 返回 true。
    str 检测字符串是否为空,不为空返回 true。 [ $a ] 返回 true。

      文件测试运算符

    操作符 说明 举例
    -b file 检测文件是否是块设备文件,如果是,则返回 true。 [ -b $file ] 返回 false。
    -c file 检测文件是否是字符设备文件,如果是,则返回 true。 [ -b $file ] 返回 false。
    -d file 检测文件是否是目录,如果是,则返回 true。 [ -d $file ] 返回 false。
    -f file 检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回 true。 [ -f $file ] 返回 true。
    -g file 检测文件是否设置了 SGID 位,如果是,则返回 true。 [ -g $file ] 返回 false。
    -k file 检测文件是否设置了粘着位(Sticky Bit),如果是,则返回 true。 [ -k $file ] 返回 false。
    -p file 检测文件是否是具名管道,如果是,则返回 true。 [ -p $file ] 返回 false。
    -u file 检测文件是否设置了 SUID 位,如果是,则返回 true。 [ -u $file ] 返回 false。
    -r file 检测文件是否可读,如果是,则返回 true。 [ -r $file ] 返回 true。
    -w file 检测文件是否可写,如果是,则返回 true。 [ -w $file ] 返回 true。
    -x file 检测文件是否可执行,如果是,则返回 true。 [ -x $file ] 返回 true。
    -s file 检测文件是否为空(文件大小是否大于0),不为空返回 true。 [ -s $file ] 返回 true。
    -e file 检测文件(包括目录)是否存在,如果是,则返回 true。 [ -e $file ] 返回 true。

      shell字符串

      单引号字符串的限制:  

        单引号里的任何字符都会原样输出,单引号字符串中的变量是无效的,单引号字符串中不能出现单引号。

      双引号字符串的优点:

        双引号里可以有变量、双引号里可以有转义字符。

      bash支持一维数组,并且没有限制数组的大小。

      定义数组

        用括号表示数组,数组元素用"空格"符号分割开。

        array_name=(value1...valuen)

    array_name=(value0 value1 value2 value3)
    或
    array_name=(
    value0 
    value1 
    value2 
    value3
    )
    

    还可以单独定义数组的各个分量:

        array_name[0]=value0
        array_name[1]=value1
        array_name[2]=value2
    

    可以不使用连续的下标,而且下标的范围没有限制。

      读取数组

      ${array_index[index]}

      使用@或*可以获取数组中的所有元素,

      获取数组长度的方法与获取字符串长度的方法相同

      length=${#array_name[@]}

      length=${#array_name[*]}

      取得数组单个元素的长度

      lengthn=${#array_name[n]}

     

      printf的移植性比echo好,是echo的增强版

      

      case ... esac 与其他语言中的switch ... case语句类似,是一种多分支选择语句。

      case语句匹配一个值或一个模式,如果匹配成功,执行相匹配的命令。

    case 值 in
    模式1)
        command1
        command2
        command3
        ;;
    模式2)
        command1
        command2
        command3
        ;;
    *)
        command1
        command2
        command3
        ;;
    esac
    

    for循环

    for 变量 in 列表
    do
        command1
        command2
        ...
        commandN
    done
    

    列表是一组值(数字、字符串等)组成的序列,每个值通过空格分隔。

    until循环执行一系列命令直至条件为true停止。

    until command
    do
       Statement(s) to be executed until command is true
    done
    

    break命令允许跳出所有循环(终止执行后面的所有循环)

      在嵌套中,break命令后面还可以跟一个数字,表示跳出第几层循环。

      break n

    continue命令不会跳出所有的循环,仅仅跳出当前循环。

      函数可以让我们讲一个复杂功能划分成若干个模块,让程序结构更加清楚,代码重复利用率更高。像其它编程语言一样,shell也支持函数。shell函数必须先定义后使用。

      shell函数的定义格式如下:

    function_name () {
        list of commands
        [ return value ]
    }
    

      也可以在函数名前加上关键字function;

      函数返回值,可以显示的增加return语句,如果不加,会将最后一条命令运行结果作为返回值。

      shell函数返回值只能是整数,一般用来表示函数执行成功与否,0表示成功,其他值表示失败。

      函数调用只需要给出函数名,不需要加括号。

      像删除变量一样,删除函数也可以使用unset命令,不过要加上.f选项。

        $unset .f function_name

      在shell中,调用函数是可以向其传递参数,在函数体内部,通过$n的形式获取参数的值。

      

      unix命令默认从标准输入设备(stdin)输入,将结果输出到标准输出设备(stdout)显示。

      输出重定向

        命令的输出不仅可以显示在显示器,还可以很容易的转移到文件,这就被称为输出重定向。

        command  > file

      输入重定向

        command < file

      输出重定向是大于号(>)输入重定向是小于号(<)

    命令 说明
    command > file 将输出重定向到 file。
    command < file 将输入重定向到 file。
    command >> file 将输出以追加的方式重定向到 file。
    n > file 将文件描述符为 n 的文件重定向到 file。
    n >> file 将文件描述符为 n 的文件以追加的方式重定向到 file。
    n >& m 将输出文件 m 和 n 合并。
    n <& m 将输入文件 m 和 n 合并。
    << tag 将开始标记 tag 和结束标记 tag 之间的内容作为输入。

      shell可以包含外部脚本,将外部脚本的内容合并到当前脚本

      shell中包含脚本可以使用:

    . filename
    或
    source filename
    

      说明:被包含脚本不需要有执行的权限。

     学习过程中的一些代码:

    仅供参考:

    新葡亰496net 2新葡亰496net 3

      1 #!/bin/bash
      2 echo "hello world !"
      3 
      4 
      5 echo "What is your name?"
      6 
      7 read PERSON
      8 
      9 echo "Hello, $PERSON"
     10 
     11 myurl="http://c.biancheng.net/cpp/view/6999.html"
     12 
     13 
     14 your_name="mozhiyan"
     15 
     16 echo $your_name
     17 
     18 echo ${your_name}
     19 
     20 for skill in Ada Coffe Action Java
     21 do
     22     echo "I am good at ${skill}Script"
     23 done
     24 
     25 
     26 echo "File Name : $0"
     27 
     28 echo "First Parameter : $1"
     29 
     30 echo "First Parameter : $2"
     31 
     32 echo "Quoted Values : $@"
     33 
     34 echo "Quoted Values : $*"
     35 
     36 echo "Total Number of Parameter : $#"
     37 
     38 
     39 echo "$*=" $*
     40 echo ""|$*"=" "$*"
     41 
     42 
     43 echo "$@=" $@
     44 echo ""|$@"=" "$@"
     45 
     46 echo "print echo Param from $*"
     47 
     48 for var in $*
     49 do
     50     echo "$var"
     51 done
     52 
     53 
     54 echo "print echo Param from $@"
     55 
     56 for var in $@ 
     57 do
     58     echo "$var"
     59 done
     60 
     61 echo "print echo Param from "$*""
     62 
     63 
     64 for var in "$*"
     65 do
     66     echo "$var"
     67 done
     68 
     69 echo "print echo Param from "$@""
     70 
     71 
     72 for var in "$@"
     73 do
     74     echo "$var"
     75 done
     76 
     77 echo $?
     78 
     79 a=10
     80 echo -e "Values of a is $a n"
     81 echo "Values of a is $a n"
     82 
     83 
     84 
     85 
     86 DATE=`data`
     87 echo "Date is $DATE"
     88 
     89 USERS=`who | wc -l`
     90 echo "Logged in user are $USERS"
     91 
     92 UP=`date ; uptime`
     93 echo "Uptime is $UP"
     94 
     95 unset var
     96 
     97 echo ${var:-"Variable is not set"}
     98 echo "1 - Value of var is ${var}"
     99 
    100 echo ${var:="Variable is not set"}
    101 echo "2 - Value of var is ${var}"
    102 
    103 unset var
    104 echo ${var: "This is default value"}
    105 echo "3 - Value of var is $var"
    106 
    107 var="Prefix"
    108 echo ${var: "This is default value"}
    109 echo "4 - Value of var is $var"
    110 
    111 echo ${var:?"Print this message"}
    112 echo "5 - Value of var is ${var}"
    113 
    114 val=`expr 2   2`
    115 echo "Total value : $val"
    116 
    117 a=10
    118 b=20
    119 
    120 val=`expr $a   $b`
    121 echo "a   b : $val"
    122 
    123 val=`expr $a - $b`
    124 echo "a - b : $val"
    125 
    126 val=`expr $a * $b`
    127 echo "a * b : $val"
    128 
    129 val=`expr $b / $a`
    130 echo "b / a : $val"
    131 
    132 val=`expr $b   $a`
    133 echo "b % a : $val"
    134 
    135 if [ $a == $b ]
    136 then
    137     echo "a is equal to b"
    138 fi
    139 
    140 if [[ $a != $b ]]; then
    141     echo "a is not equal to b"
    142 fi
    143 
    144 
    145 
    146 
    147 a=10
    148 b=20
    149 if [ $a -eq $b ]
    150 then
    151    echo "$a -eq $b : a is equal to b"
    152 else
    153    echo "$a -eq $b: a is not equal to b"
    154 fi
    155 
    156 if [ $a -ne $b ]
    157 then
    158    echo "$a -ne $b: a is not equal to b"
    159 else
    160    echo "$a -ne $b : a is equal to b"
    161 fi
    162 
    163 if [ $a -gt $b ]
    164 then
    165    echo "$a -gt $b: a is greater than b"
    166 else
    167    echo "$a -gt $b: a is not greater than b"
    168 fi
    169 
    170 if [ $a -lt $b ]
    171 then
    172    echo "$a -lt $b: a is less than b"
    173 else
    174    echo "$a -lt $b: a is not less than b"
    175 fi
    176 
    177 if [ $a -ge $b ]
    178 then
    179    echo "$a -ge $b: a is greater or  equal to b"
    180 else
    181    echo "$a -ge $b: a is not greater or equal to b"
    182 fi
    183 
    184 if [ $a -le $b ]
    185 then
    186    echo "$a -le $b: a is less or  equal to b"
    187 else
    188    echo "$a -le $b: a is not less or equal to b"
    189 fi
    190 
    191 a=10
    192 b=20
    193 
    194 if [ $a != $b ]; then
    195     echo "$a != $b : a is not equal to b"
    196 else
    197     echo "$a == $b : a is equal to b"
    198 fi
    199 
    200 if [ $a -lt 100 -a $b -gt 15 ]
    201 then
    202     echo "$a -lt 100 -a $b -gt 15 :return true"
    203 else
    204     echo "$a -lt 100 -a $b -gt 15 :return false"
    205 fi
    206 
    207 if [ $a -lt 100 -o $b -gt 100 ]
    208 then
    209     echo "$a -lt 100 -o $b -gt 100 :return true"
    210 else
    211     ecjo "$a -lt 100 -o $b -gt 100 :return false"
    212 fi
    213 
    214 
    215 if [ $a -lt 5 -o $b -gt 100 ]
    216 then
    217     echo "$a -lt 5 -o $b -gt 100 :return true"
    218 else
    219     echo "$a -lt 5 -o $b -gt 100 :return false"
    220 fi
    221 
    222 
    223 
    224 a="abc"
    225 b="efg"
    226 
    227 if [ $a = $b ]
    228 then
    229    echo "$a = $b : a is equal to b"
    230 else
    231    echo "$a = $b: a is not equal to b"
    232 fi
    233 
    234 if [ $a != $b ]
    235 then
    236    echo "$a != $b : a is not equal to b"
    237 else
    238    echo "$a != $b: a is equal to b"
    239 fi
    240 
    241 if [ -z $a ]
    242 then
    243    echo "-z $a : string length is zero"
    244 else
    245    echo "-z $a : string length is not zero"
    246 fi
    247 
    248 if [ -n $a ]
    249 then
    250    echo "-n $a : string length is not zero"
    251 else
    252    echo "-n $a : string length is zero"
    253 fi
    254 
    255 if [ $a ]
    256 then
    257    echo "$a : string is not empty"
    258 else
    259    echo "$a : string is empty"
    260 fi
    261 
    262 your_name="yinxin"
    263 greeting="hello, "$your_name" !"
    264 greeting_1="hello, ${your_name} !"
    265 
    266 echo $greeting $greeting_1
    267 
    268 string="abcd"
    269 echo ${#string}
    270 
    271 string="alibaba is a great company"
    272 echo `expr index "$string" is`
    273 
    274 string="alibaba is a great company"
    275 echo ${string:1:4}
    276 
    277 NAME[0]="Zare"
    278 NAME[1]="Qadir"
    279 NAME[2]="Mahnaz"
    280 NAME[3]="Ayan"
    281 NAME[4]="Daisy"
    282 echo "First Index : ${NAME[0]}"
    283 
    284 echo "Second Index: ${NAME[1]}"
    285 
    286 echo "First Method: ${NAME[@]}"
    287 
    288 echo "Second Method: ${NAME[*]}"
    289 
    290 echo "${#NAME[@]}"
    291 
    292 echo "${#NAME[*]}"
    293 
    294 echo "${#NAME[2]}"
    295 
    296 echo `date`
    297 
    298 # format-string为双引号
    299 printf "%d %sn" 1 "abc"
    300 #1 abc
    301 # 单引号与双引号效果一样 
    302 printf '%d %sn' 1 "abc" 
    303 #1 abc
    304 # 没有引号也可以输出
    305 printf %s abcdef
    306 #abcdef
    307 # 格式只指定了一个参数,但多出的参数仍然会按照该格式输出,format-string 被重用
    308 printf %s abc def
    309 #abcdef
    310 printf "%sn" abc def
    311 #abc
    312 #def
    313 printf "%s %s %sn" a b c d e f g h i j
    314 #a b c
    315 #d e f
    316 #g h i
    317 #j
    318 # 如果没有 arguments,那么 %s 用NULL代替,%d 用 0 代替
    319 printf "%s and %d n" 
    320 #and 0
    321 # 如果以 %d 的格式来显示字符串,那么会有警告,提示无效的数字,此时默认置为 0
    322 printf "The first program always prints'%s,%dn'" Hello Shell
    323 #-bash: printf: Shell: invalid number
    324 #The first program always prints 'Hello,0'
    325 
    326 
    327 echo "Input a number between 1 to 4"
    328 echo 'Your number is:c'
    329 read aNum
    330 
    331 case $aNum in
    332     1)
    333     echo "You select 1"
    334     ;;
    335     2)
    336     echo "You select 2"
    337     ;;
    338     3)
    339     echo "You select 3"
    340     ;;
    341     4)
    342     echo "You select 4"
    343     ;;
    344     *)
    345     echo "You do not select a number between 1 to 4"
    346     ;;
    347 esac
    348 
    349 
    350 
    351 for File in $HOME/* 
    352 do
    353     echo $File
    354 done
    355 
    356 
    357 for File in $HOME/.bash*  
    358 do
    359     echo $File
    360 done
    361 
    362 a=0
    363 until [ ! $a -lt 10 ]
    364 do
    365     echo $a
    366     a=`expr $a   1`
    367 done
    368 
    369 Hello () {
    370     echo "Url is http://c.biancheng.net/cpp/view/7011.html"
    371 }
    372 
    373 
    374 Hello
    375 
    376 while :
    377 do
    378     echo -n "Input a number between 1 to 5: "
    379     read aNum
    380     case $aNum in
    381         1|2|3|4|5)
    382             echo "Your number is $aNum!"
    383             ;;
    384         *)
    385             echo "Your do not select a number between 1 to 5!"
    386             continue
    387             echo "Game is over!"
    388             ;;
    389     esac
    390 done
    

    View Code

     

    学习shell脚本的过程全部参考来自:

    本文由新葡亰496net发布于电脑系统,转载请注明出处:新葡亰496netShell脚本语言,基本操作小结

    关键词: