bash脚本编程语法:

  • 字符表示相关:

没有被单引号括起的’\’表示其后所接的字符为字符字面意义。除了在行末表示两行连接。


单引号括起表示单引号内左右字符为字面意义,其中不能再出现单引号,即使前面加反斜线’\’。


双引号括起表示其内部所有的字符为字面意义,但 ’$’, ‘`’, ‘\’,’!’例外

’$’, ‘`’ 保持特殊意义,’\’只有在’$’, ’`’, ’”’ , ’\’,换行字符跟随时才保留特殊意义

’\’后字符没有特殊意义的,不做修改

双引号内可以使用双引号,但要加’\’。

‘!’保留特殊意义,除非前面加‘\’

特殊参数‘*’和’@’在双引号内有特殊意义


ANSI-C



  • 变量:


    • 等号两侧不能加空格,如果加空格,那么Shell会认为是执行name命令加上参数


    • 命名方式与c类似


    • $1,$2,$3等是Shell用来解析命令行参数的特殊变量,只读不可写


    • 当Shell遇到$时,首先读取符号$后面的一个字符串,把这个字符串当作一个变量名,然后依据这个变量名读取出变量的值,然后代替$符号和变量名整体。这叫变量替换


    • Shell脚本中的变量可以不用事先定义直接引用,如果为空则相当于空变量,返回一个空字符


    • read命令可以把用户的输入赋值给变量,unset可一删除一个定义过的变量


    • 为了某一个程序在一个特定的环境执行,而不改变当前的shell命令,可以使用如下形式


var1=value,var2=value,var3=value... program


    • readonly定义只读变量


      两种方法:


1:

VERSION=2.0

readonly VERSION

2:

readonly VERSION=2.0


  • 数组变量:


    ${arr[*]}为数组作为一个整体进行替代,而${arr[@]}是作为元素列表进行替代。"${arr[@]}"与${arr[*]}等价


    for i in "${arr[@]}" 和for i in ${arr[*]}和for i in ${arr[@]}的输出是相同的


    但for i in "${arr[*]}"是不一样的


${arr[*]}和${arr[@]}的不同在于加引号时的区别,不加时都是拓展为元素列表

${arr[*]}加引号拓展为整体,而${arr[@]}加引号时拓展为元素列表


双引号括起的就是一个字符串

for循环右边是多个元素,不是一个字符串进行分割


赋值方式:

array[index]=value

array=(value0 value1 value2) //会覆盖元素

array=([2]=value2 [0]=value0 [1]=value1) //会覆盖元素

删除变量:

unset arr[0]:删除一个元素

unset arr、unset arr[@]、unset arr[*]为删除整个数组


array=([2]=value2 value3 value4) 序号依第一个递增

${#arr[@]}获得数组元素个数



  • 环境变量

export name=value

export name

子进程和父进程的同名环境变量所处的存储位置不一样,不能相互影响


  • Shell变量   man bash Shell Variables处有所有shell变量


    HOME

    当前用户的主目录

    SHELL

    当前用户所使用的Shell程序

    USER

    当前的登录用户

    UID

    拓展为当前用户数字的user id

    BASH_VERSION

    当前使用的bash版本

    PWD

    当前工作目录

    OLDPWD

    前一个工作目录

    SECONDS

    shell执行了多长时间

    SHLVL

    当前bash在shell的第几层子进程

    RANDOM

    产生0到32767的随机数

    IFS

    分隔符

    PATH

    到哪些目录去搜索可执行文件


    set命令可以查看Shell中所有的变量和函数定义,export -p 和env命令可以查看到所有被export导出到环境中的变量


  • 特殊变量


    特殊变量$#表示有多少个参数


    可用内建命令shfit删除第一个参数,指定参数n可以使shift删除多个参数,shift "$#" 删除全部参数


$?上条命令执行的返回值,非0则发生错误

$$为进程所在的PID

$@代表命令行中的所有参数列表

$*代表命令行所有参数整体




  • 流程控制


    • 二元操作符


      -eq

      等于

      -ne

      不等于

      -le

      小于等于

      -gt

      大于

      -ge

      大于等于


      如果then和if [ ... ] 写在一行,then的前面需要加分号


      elif不能写成else if


      如果使用elif语句,后面也要加then


      不要忘记结束标记fi


      内建测试命令 [ ]方括号两边都得有空格,好歹也是命令啊




    • if语句后面接的是命令


      即 [ 是个命令,后面的表达式、] 都可以认为是选项。


      if语句后面的返回值是0,则认为条件满足




    • case语句


      语法:case word in [[(]pattern [|pattern]...) command-list ;;]... esac



      case "$option" in


      "O"|"o")


      echo "successed!"


      ;;


      *)


      command-list


      ;;


      esac


      每个子句需要;;、;&或;;&来结束,区别在于

      ;;为即使后面还有匹配的pattern也不会执行子句


      ;&为结尾会继续执行下一个子句中的command-list,如过下个子句的结尾以;&或;;&结尾,那么按照相应规则一直到;;结尾,具有传递性,一发不可收拾


      ;;&为结尾会以执行后面子句中,符合pattern的。




    • while循环


      语法:while test-commands; do consequent-commands; done


      do标志循环体的开始。




test-commands可以是多个命令构成的一个list,由分号分开每个命令,决定是否退出循环的是最后一个命令的返回值。



    • until循环


      语法:until test-commands;do consequent-commands;done



字符串操作符

用的和字符和数字的操作符是不一样滴

-n STRING

长度非0返回真

-z STRING

长度为0返回真

STRING1 = STRING2

字符串相同返回0

STRING1 != STRING2

两个字符串不相同返回真



    • for循环


      语法:for name [in [words ...];] do cpmmands;done


      for FILE in *.sh



    c式for

for( ( i=1;i <= 100; i++))

单括号改为双括号,花括号改为do和done,变量不用加$。连空格都不用在意了。




    • select循环


      语法:select name [in woeds...] ;do commands;done


      无论输入什么,都会保存到变量$REPLY中


      如果输入的数字和显示的标号不匹配,则不会保存到name中


      无论用户输入与菜单项数字是否匹配,都会执行do和done之间的循环体。没有输入直接按ehter键什么也不执行,与再次执行select语句一样再次输出所有的菜单项和提示符。会执行select之前的语句。


      循环体执行需要手动break或exit



    select的循环默认提示符是#?,可在脚本开始后加入PS3="Please make a selection =>"



    • break和continue语句


      break [n]         continue [n]




  • 函数

NTMD终于到你了。

定义格式

name()

{

command-list;

}


function name() 这里括号可省

{

command-list;

}



定义函数时函数体不能为空,调用函数时不加括号()。$0是脚本的执行路径,对于脚本来说



命令行里可以定义函数,用declare -f 查看所声明的函数定义,用unset取消函数声明。


参数

使用$1引用第一个参数,剩余类似。

注意$0仍然引用脚本名称。




使用例子,分解$1保存的IP:

local IFS=. //设置分隔符,local修饰表示只在本函数内生效

set -- $1 //拆散$1,保存在$1,$2,$3,$4.这会摧毁其它参数。


注意不要混淆函数输出和退出状态,函数也可以用命令替换。


变量作用域:函数内定义的,也是全局变量,可用local关键字声明局部变量,使作用域限制在函数内。但函数内定义的函数,只有外层函数被调用后才生效。脚本就是脚本。