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关键字声明局部变量,使作用域限制在函数内。但函数内定义的函数,只有外层函数被调用后才生效。脚本就是脚本。