shell脚本编程

293 阅读4分钟

一、变量

  • 用户自定义变量设置与使用

    • 变量名只能是英文字母或数字,不能以数字开头
    • 等号两边不能加空格
    • 单引号内的特殊字符仅为存文本,双引号内特殊字符有特殊含义
    lcx@Ubuntu:~$ var=hello				#创建一个变量,将值hello赋值给var
    lcx@Ubuntu:~$ echo ${var}			#echo—>打印,${变量名}->取出变量中的值
    hello
    lcx@Ubuntu:~$ var="$var"wo			#向变量var后添加两个字符wo
    lcx@Ubuntu:~$ echo "$var"			#打印变量的另一种方法
    hellowo
    lcx@Ubuntu:~$ var=${var}rld			#向变量var后添加数据的另一种方式
    lcx@Ubuntu:~$ echo $var				#打印变量的另一种方法
    helloworld
    lcx@Ubuntu:~$
    
  • 取消设置变量

    lcx@Ubuntu:~$ unset var				#取消设置变量var
    lcx@Ubuntu:~$ echo ${var}			
    									#bash变量类型默认为字符串,因此打印为空字符串
    lcx@Ubuntu:~$ 
    
  • 环境变量

    • 用户自定义变量仅在当前bash生效
    #在当前bash中设置一个变量var的值为helloworld
    lcx@Ubuntu:~$ var=helloworld
    lcx@Ubuntu:~$ echo ${var}
    helloworld
    lcx@Ubuntu:~$ bash 						#启动一个子bash
    lcx@Ubuntu:~$ echo  ${var}				#在子bash中查看变量var,发现未被设置
    
    lcx@Ubuntu:~$ 
    
    • 环境变量的设置
    #在当前bash中设置一个环境变量var的值为helloshell
    lcx@Ubuntu:~$ export value=helloshell
    lcx@Ubuntu:~$ echo ${value}
    helloshell
    lcx@Ubuntu:~$ bash					#启动一个子bash
    lcx@Ubuntu:~$ echo ${value}			#在子bash中查看变量var
    helloshell
    lcx@Ubuntu:~$ exit					#退出当前bash
    
    • env查看所有环境变量
    lcx@Ubuntu:~$ env
    SSH_CONNECTION=111.22.250.7 64573 172.24.42.51 22
    LESSCLOSE=/usr/bin/lesspipe %s %s
    LANG=en_US.UTF-8
    DISPLAY=localhost:10.0
    S_COLORS=auto
    XDG_SESSION_ID=3093
    USER=lcx
    PWD=/home/lcx
    HOME=/home/lcx
    SSH_TTY=/dev/pts/0
    MAIL=/var/mail/lcx
    TERM=xterm
    SHELL=/bin/bash
    。。。。。
    
  • 设置变量类型

    • bash环境中变量类型默认为字符串
    • 变量的数值运算仅能达到整数形态,如果想计算含有小数的表达式,可以用bc命令
    lcx@Ubuntu:~$ sum=1+2+3				
    lcx@Ubuntu:~$ echo ${sum}				#sum的类型默认为字符串,所有显示1+2+3
    1+2+3
    lcx@Ubuntu:~$ declare -i sum=1+2+3		#将sum的类型设置为整型
    lcx@Ubuntu:~$ echo ${sum}				#显示1+2+3的和
    6
    lcx@Ubuntu:~$ echo "17.2*23.7" | bc	  # |是管道符,用于将前一个命令的输出,作为后一个命令的输入
    407.6
    lcx@Ubuntu:~$ 
    
    • declare和typeset
      #declaretypeset的功能一样
      lcx@Ubuntu:~$ declare 参数 变量名
      	-i:将变量声明为整型
      	-a:将变量声明为数组
      	-x:将变量声明为环境变量
      	-r:将变量设置为只读
    
  • 接收键盘的输入

    lcx@Ubuntu:~$ read value				#接受键盘的输入,将值存入value中
    123
    lcx@Ubuntu:~$ echo ${value}
    123
    lcx@Ubuntu:~$ read -p "请输入:" value	  #接受键盘的输入并显示提示信息
    请输入:1234
    lcx@Ubuntu:~$ echo ${value}
    1234
    lcx@Ubuntu:~$ read -t 1 value			#接受键盘的输入,只等待一秒,若无输入则直接返回
    lcx@Ubuntu:~$ 
    
  • 变量内容的删除

    #PATH是系统自带的环境变量
    lcx@Ubuntu:~$ echo ${PATH}
    /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
    ##’代表要从前往后删除最短匹配,/*: 表示删除第一个字符是/,最后一个字符是:,*是通配符代表任意个字符
    lcx@Ubuntu:~$ echo ${PATH#/*:}
    /usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin	#/usr/local/sbin:被删除了
    lcx@Ubuntu:~$ echo ${PATH##/*:}					# ‘##’代表从前往后删除最长匹配的字符
    /bin
    lcx@Ubuntu:~$
    

    %和#功能差不多,只是%是从后往前删除字符,#是从前往后删除字符

    lcx@Ubuntu:~$ echo ${path}
    /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
    lcx@Ubuntu:~$ echo ${path%:*}
    /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin
    lcx@Ubuntu:~$ echo ${path%%:*}
    /usr/local/sbin
    lcx@Ubuntu:~$ 
    
  • 变量内容的替换

    ${变量/旧字符串/新字符串} 将第一个旧字符串替换为新字符串

    ${变量//旧字符串/新字符串} 将全部的旧字符串替换为新字符串

    lcx@Ubuntu:~$ echo ${path}
    /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
    lcx@Ubuntu:~$ echo ${path/local/LOCAL}
    /usr/LOCAL/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
    lcx@Ubuntu:~$ echo ${path//local/LOCAL}
    /usr/LOCAL/sbin:/usr/LOCAL/bin:/usr/sbin:/usr/bin:/sbin:/bin
    lcx@Ubuntu:~$ 
    
  • 变量是否存在

    #如果oldValue不存在且不为为空字符,则将notExist赋给newValue
    lcx@Ubuntu:~$ newValue=${oldValue-notExist}
    lcx@Ubuntu:~$ echo ${newValue}
    notExist
    lcx@Ubuntu:~$ oldValue=""
    lcx@Ubuntu:~$ newValue=${oldValue-notExist}	   #此时oldValue为空字符,则newValue也为空字符
    lcx@Ubuntu:~$ echo ${newValue}
    
    lcx@Ubuntu:~$ newValue=${oldValue:-notExist}   #如果在-前面加:则即使oldValue为空字符,也将
    lcx@Ubuntu:~$ echo ${newValue}				   # newValue设置为notExist
    notExist
    lcx@Ubuntu:~$ 
    

    有关变量测试及替换还有很多方法,可以自行了解。

  • 通配符

    符号 含义
    * 代表0到无穷多个任意字符
    代表一个任意字符
    [] 代表一个在[]里的字符,例如[abcd],则代表a、b、c、d任何一个字符
    [-] 代表范围内任意一个字符,例如[0-9]代表0和9之间的任意一个数字
    [^] 反向选择。例如[ ^abcd ]代表不是a、b、c、d的任意一个字符

二、控制流

  • shell脚本的执行方式

    • source script
    • bash script
    • sh script
    • ./ script
    #编写一个脚本接收用户的输入并打印
    lcx@Ubuntu:~/shell$ vi test.sh
    lcx@Ubuntu:~/shell$ cat test.sh 		#使用cat查看文件内容
    #!/bin/bash
    read -p "请输入:" value
    echo ${value}
    lcx@Ubuntu:~/shell$ sh test.sh 
    请输入:aaa
    aaa
    lcx@Ubuntu:~/shell$ echo ${value}		#发现我们在脚本中设置的变量在bash竟然无效?
    
    lcx@Ubuntu:~/shell$ 
    

    ​ 在脚本中设置的变量在bash中无效的原因是因为,如果我们使用bash 、sh或者./的方式执行脚本时,实际上是启用了一个新的bash进程来执行我们的脚本,变量里我们讲了,用户自定义变量在进程间是不共享的,因此我们在主bash进程打印value变量时,发现它未被设置。

    #如果想要脚本中设置的变量在主bash中生效,可以用source来执行脚本
    lcx@Ubuntu:~/shell$ source test.sh 
    请输入:ccc
    ccc
    lcx@Ubuntu:~/shell$ echo ${value}
    ccc
    lcx@Ubuntu:~/shell$ 
    
  • shell脚本的默认变量

    ​ 当我们执行脚本时,是可以通过命令行向shell脚本传递参数的。我们可以在脚本内通过如下变量来调用命令行传递的参数,这些变量都是shell自带的:

    • $# 代表通过命令行传递的参数的个数
    • $num num是一个数字,$0代表当前shell脚本的名字,$1代表传递的第一个参数,以此类推。
    • $num num是一个数字,$0代表当前shell脚本的名字,$1代表传递的第一个参数,以此类推。
    • $@ 代表传递的所有参数,每个变量用双引号括起来,[”$1“,"$2","$3"]
    • $* 代表传递的所有参数,每个变量用双引号括起来,[”$1c$2c$3"]c是间隔符,默认是空格。
    lcx@Ubuntu:~$ cat test.sh 
    #!/bin/bash
    
    echo "the script name is $0"
    echo "you afferented parameter number is $#"
    echo "the first parameter is $1"
    echo "the parameter is $@"
    echo "the parameter is $*"
    lcx@Ubuntu:~$ bash test.sh a b c d
    the script name is test.sh
    you afferented parameter number is 4
    the first parameter is a
    the parameter is a b c d
    the parameter is a b c d
    lcx@Ubuntu:~$
    
  • if判断语句

    if [条件判断];then

    ​ do_something

    elif [条件判断];then

    ​ do_something

    else

    ​ 上述判断式都不成立时执行

    fi <——结束标记

    lcx@Ubuntu:~$ cat test.sh 
    #!/bin/bash
    
    if [ "$1>$2" ];then
        echo "$1>$2"
    elif [ "$1==$2" ];then
        echo "$2=$1"
    else
        echo "${2}>${1}"
    fi
    lcx@Ubuntu:~$ bash test.sh 10 10
    10=10
    lcx@Ubuntu:~$ 
    
  • 判断符号 []

    ​ 如果使用中括号作为shell的判断式时,必须要注意中括号的两端需要有空格符来分隔,在中括号内的变量最好都以双引号括起来。中括号内的常量最好都以单或双引号括起来。

    • 数字和字符串判断
    参数 意义
    -eq 两数相等
    -ne 两数不相等
    -gt 左边的数大于右边的数
    -lt 左边的数小于右边的数
    -ge 左边的数大于等于右边的数
    -le 左边的数小于等于右边的数
    test -z string 判断string是否为空字符串,是则返回true
    test -n string 判断string是否为非空字符串,是则返回true
    test str1==str2 判断str1和str2是否相等,是则返回true
    • 多重条件判断
    参数 意义
    -a 两边条件同时成立时,返回true
    -o 两边条件只要有一个成立时,返回true
    取反
    #可以将上述if的例子转换为如下
    lcx@Ubuntu:~$ cat test.sh 
    #!/bin/bash
    
    if [ "$1 -gt $2" ];then
        echo "$1>$2"
    elif [ "$1 -eq $2" ];then
        echo "$2=$1"
    else
        echo "${2}>${1}"
    fi
    lcx@Ubuntu:~$ bash test.sh 10 10
    10=10
    lcx@Ubuntu:~$ 
    
  • case选择语句

    case $变量名 in

    ​ "变量内容")

    ​ do_something

    ;;

    ​ "变量内容")

    ​ do_something

    ;;

    ​ *) <——其他所有值

    ​ do_something

    ;;

    esac <——结束标记

lcx@Ubuntu:~$ cat test.sh 
#!/bin/bash

case $1 in
    "hello")
        echo "hello world"
        ;;
        *)
        echo "input is not what I want"
        ;;
esac
lcx@Ubuntu:~$ bash test.sh hello
hello world
lcx@Ubuntu:~$ 
  • 固定循环次数语句

    for var in v1 v2 v3...

    do

    ​ do_something

    done <——结束标记

lcx@Ubuntu:~$ cat test.sh 
#!/bin/bash

for animal in cat dog rabbit mouse
do
    echo "the animals have ${animal}"
done
lcx@Ubuntu:~$ bash test.sh 
the animals have cat
the animals have dog
the animals have rabbit
the animals have mouse
lcx@Ubuntu:~$ 
  • 不固定循环次数语句

    • while [判断式]

      do

      ​ do_something

      done <——结束标记

    #while只要判断式为真,就会执行dodone之间的语句
    lcx@Ubuntu:~$ cat test.sh 
    #!/bin/bash
    
    declare -i i=0
    while [ "${i}" -lt "5" ]
    do
        echo "${i}"
        i=${i}+1
    done
    lcx@Ubuntu:~$ bash test.sh 
    0
    1
    2
    3
    4
    lcx@Ubuntu:~$		
    
    • until [判断式]

      do

      ​ do_something

      done <——结束标记

#until只要判断是为假,就进入循环
lcx@Ubuntu:~$ cat test.sh 
#!/bin/bash

declare i=0
until [ "${i}" -gt "5" ]
do
    echo "${i}"
    i=$((${i}+1))
done
lcx@Ubuntu:~$ bash test.sh 
0
1
2
3
4
5
lcx@Ubuntu:~$ 

三、函数

function 函数名() {

​ do_something

​ return 返回值 <——可以省略

}

​ 函数也拥有内置变量,并且与shell脚本类似,$0代表函数名,$1第一个参数,$2第二个参数。。。。

lcx@Ubuntu:~$ cat test.sh 
#!/bin/bash

function mFunc(){
    declare -i i=${1}
    echo "the function name is $0)"
    until [ "${i}" -gt "5" ]
    do
        i=${i}+1
        echo "${i}"
    done

    return ${i}
}

mFunc i

echo "i after function end is $?"
lcx@Ubuntu:~$ bash test.sh 
the function name is test.sh)
1
2
3
4
5
6
i after function end is 6
lcx@Ubuntu:~$

?返回的是上一条命令的返回值,也可以用来表示函数的返回值,如果在函数返回后没有立即保存返回值,则其返回值不能再通过?获得。