• 01_SHELL编程之变量定义(二)


    变量的定义

    ###1. 变量的分类

    • 本地变量:当前用户自定义的变量。当前进程中有效,其他进程及当前进程的子进程无效。

    • 环境变量:当前进程有效,并且能够被子进程调用。

      • 查看当前用户的环境变量 env

      • 查询当前用户的所有变量(临时变量与环境变量) set

      • export //将当前变量变成环境变量

    [root@MissHou tmp]# export A=hello      //临时将一个本地变量(临时变量)变成环境变量
    [root@MissHou tmp]# env|grep ^A
    A=hello
    ​
    永久生效:
    vim /etc/profile 或者 ~/.bashrc
    export A=hello
    或者
    A=hello
    export A
    ​
    说明:系统中有一个变量PATH,环境变量
    export PATH=/usr/local/mysql/bin:$PATH
    ​
    • 全局变量:全局所有的用户和程序都能调用,且继承,新建的用户也默认能调用.

    $HOME/.bashrc           当前用户的bash信息(aliase、umask等)
    $HOME/.bash_profile     当前用户的环境变量()
    oracle——>oracle用户——>$oracle/.bash_profile——>export home_install=/u01/app/xxx
    ​
    $HOME/.bash_logout          每个用户退出当前shell时最后读取的文件
    ​
    /etc/bashrc             使用bash shell用户全局变量
    grep --color=auto
    umask
    ​
    /etc/profile           系统和每个用户的环境变量信息
    ​
    mycat_home=/usr/local/mycat/bin
    export mycat_home
    执行mycat命令
    # mycat
    $ mycat
    ​
    用户登录系统读取相关文件的顺序:
    /etc/profile——>$HOME/.bash_profile——>$HOME/.bashrc——>/etc/bashrc——>$HOME/.bash_logout
    ​
    source /etc/bashrc
    ​
    • 系统变量(内置bash中变量) : shell本身已经固定好了它的名字和作用.

    $?:上一条命令执行后返回的状态,当返回状态值为0时表示执行正常,非0值表示执行异常或出错
     若退出状态值为0,表示命令运行成功
     若退出状态值为127,表示command not found
     若退出状态值为126,表示找到了该命令但无法执行(权限不够)
     若退出状态值为1&2,表示没有那个文件或目录
     
    $$:当前所在进程的进程号     echo $$   eg:kill -9 `echo $$`  = exit   退出当前会话
    $!:后台运行的最后一个进程号  (当前终端)  # gedit &
    !$  调用最后一条命令历史中的参数
    !!  调用最后一条命令历史
    ​
    ​
    $#:脚本后面接的参数的个数
    $*:脚本后面所有参数,参数当成一个整体输出,每一个变量参数之间以空格隔开
    $@: 脚本后面所有参数,参数是独立的,也是全部输出
    ​
    $0:当前执行的进程/程序名  echo $0     
    $1~$9 位置参数变量
    ${10}~${n} 扩展位置参数变量  第10个位置变量必须用{}大括号括起来
    ./1.sh a b c
    ​
    [root@MissHou shell01]# cat 2.sh 
    #!/bin/bash
    #xxxx
    echo "\$0 = $0"
    echo "\$# = $#"
    echo "\$* = $*"
    echo "\$@ = $@"
    echo "\$1 = $1" 
    echo "\$2 = $2" 
    echo "\$3 = $3" 
    echo "\$11 = ${11}" 
    echo "\$12 = ${12}" 
    ​
    了解$*和$@的区别:
    $*  :表示将变量看成一个整体
    $@  :表示变量是独立的
    ​
    #!/bin/bash
    for i in "$@"
    do
    echo $i
    done
    ​
    echo "======我是分割线======="
    ​
    for i in "$*"
    do
    echo $i
    done
    ​
    [root@MissHou shell01]# bash 3.sh a b c
    a
    b
    c
    ======我是分割线=======
    a b c
    ​

    ###2. 什么时候需要定义变量?

    • 如果某个内容需要多次使用,并且在代码中重复出现,那么可以用变量代表该内容。这样在修改内容的时候,仅仅需要修改变量的值。

    • 在代码运作的过程中,可能会把某些命令的执行结果保存起来,后续代码需要使用这些结果,就可以直接使用这个变量。

    ###3. 变量的定义规则

    1. 默认情况下,shell里定义的变量是不分类型的,可以给变量赋与任何类型的值;等号两边不能有空格,对于有空格的字符串做为赋值时,要用引号引起来
    变量名=变量值
    ​
    2. 变量的获取方式: $变量名     ${变量名} 
    [root@MissHou shell01]# a=12345678
    [root@MissHou shell01]# echo $a
    12345678
    [root@MissHou shell01]# echo ${a}
    12345678
    [root@MissHou shell01]# echo ${a:2:3}       a表示变量名;2表示从第3个字符开始;3表示后面3个字符
    345
    ​
    如果获取变量的全部两个都可以;如果获取变量的某一部分,用${}
    ​
    3. 取消变量:     unset  变量名
    ​
    4. 变量名区分大小写,同名称但大小写不同的变量名是不同的变量
    5. 变量名可以是字母或数字或下划线,但是不能以数字开头或者特殊字符
    [root@MissHou shell01]# 1a=hello
    -bash: 1a=hello: command not found
    [root@MissHou shell01]# ?a=hello
    -bash: ?a=hello: command not found
    [root@MissHou shell01]# _a=hello
    [root@MissHou shell01]# echo $_a
    hello
    ​
    6. 命令的执行结果可以保存到变量
    [root@server shell01]# kernel=`uname -r`
    [root@server shell01]# echo $kernel
    2.6.32-431.el6.x86_64
    [root@server shell01]# name=$(uname -n)
    [root@server shell01]# echo $name
    server.itcast.cc
    ​
    7. 有类型变量 declare
    -i 将变量看成整数 
    -r 使变量只读  readonly
    -x 标记变量通过环境导出  export
    -a  指定为索引数组(普通数组);查看普通数组
    -A 指定为关联数组;查看关联数组
    ​
    [root@server shell01]# a=10
    [root@server shell01]# b=20
    [root@server shell01]# echo $a+$b
    10+20
    ​
    [root@server shell01]# declare -i a=2
    [root@server shell01]# declare -i b=4
    [root@server shell01]# declare -i c=$a+$b
    [root@server shell01]# echo $c
    6
    ​
    [root@server shell01]# AAAA=hello
    [root@server shell01]# export AAAA
    [root@server shell01]# env|grep AAAA
    AAAA=hello
    [root@server shell01]# declare -x BBBB=hello
    [root@server shell01]# env|grep BBBB
    BBBB=hello
    ​
    ​
    8. 数组
    普通数组:只能使用整数作为数组索引(元素的下标)
    关联数组:可以使用字符串作为数组索引(元素的下标)
    ​
    普通数组定义:用括号来表示数组,数组元素(变量)用“空格”符号分割开。定义数组的一般形式为:
    一次赋一个值:
    变量名=变量值
    array[0]=v1
    array[1]=v2
    array[3]=v3
    一次赋多个值:
    array=(var1 var2 var3 var4)
    array1=(`cat /etc/passwd`)          //将文件中每一行赋值给array1数组
    array2=(`ls /root`)
    array3=(harry amy jack "Miss Hou")
    array4=(1 2 3 4 "hello world" [10]=linux)
    ​
    读取数组:
    ${array[i]}  i表示元素的下标
    使用@ 或 * 可以获取数组中的所有元素:
    获取第一个元素
    echo ${array[0]}
    echo ${array[*]}            获取数组里的所有元素
    echo ${#array[*]}           获取数组里所有元素个数
    echo ${!array[@]}       获取数组元素的索引下标
    echo ${array[@]:1:2}    访问指定的元素;1代表从下标为1的元素开始获取;2代表获取后面几个元素
    ​
    ​
    [root@server shell01]# array[0]=var1
    [root@server shell01]# array[1]=var2
    [root@server shell01]# array[2]=var3
    [root@server shell01]# array1=(uu1 uu2 uu3 uu4)
    [root@server shell01]# ls
    1.sh  2.sh  3.sh  4.sh  passwd
    [root@server shell01]# array2=(`ls ./`)
    [root@server shell01]# array3=(jack harry "Miss Hou" [5]=tom)
    ​
    查看普通数组信息:
    [root@server shell01]# declare -a
    declare -a array='([0]="var1" [1]="var2" [2]="var3")'
    declare -a array1='([0]="uu1" [1]="uu2" [2]="uu3" [3]="uu4")'
    declare -a array2='([0]="1.sh" [1]="2.sh" [2]="3.sh" [3]="4.sh" [4]="passwd")'
    declare -a array3='([0]="jack" [1]="harry" [2]="Miss Hou" [5]="tom")'
    [root@server shell01]# 
    [root@server shell01]# 
    [root@server shell01]# echo ${array[*]}
    var1 var2 var3
    [root@server shell01]# echo ${array[@]}
    var1 var2 var3
    [root@server shell01]# echo ${array[2]}
    var3
    [root@server shell01]# echo ${array2[@]}
    1.sh 2.sh 3.sh 4.sh passwd
    [root@server shell01]# echo ${array2[3]}
    4.sh
    [root@server shell01]# 
    [root@server shell01]# echo ${array2[*]:2:2}
    3.sh 4.sh
    [root@server shell01]# echo ${#array2[*]}
    5
    [root@server shell01]# echo ${!array2[*]}
    0 1 2 3 4
    [root@server shell01]# echo ${!array3[*]}
    0 1 2 5
    ​
    ​
    关联数组定义:
    首先声明关联数组
    declare -A asso_array1
    declare -A asso_array2
    declare -A asso_array3
    ​
    数组赋值:
    一次赋一个值:
    数组名[索引|下标]=变量值
    [root@server ~]# asso_array1[linux]=one
    [root@server ~]# asso_array1[java]=two
    [root@server ~]# asso_array1[php]=three
    一次赋多个值:
    [root@server ~]# asso_array2=([name1]=harry [name2]=jack [name3]=amy [name4]="Miss Hou")
    查看关联数组:
    [root@server ~]# declare -A
    declare -A asso_array1='([php]="three" [java]="two" [linux]="one" )'
    declare -A asso_array2='([name3]="amy" [name2]="jack" [name1]="harry" [name4]="Miss Hou" )'
    ​
    [root@server ~]# echo ${asso_array1[linux]}
    one
    [root@server ~]# echo ${asso_array1[php]}
    three
    [root@server ~]# echo ${asso_array1[*]}
    three two one
    [root@server ~]# echo ${!asso_array1[*]}
    php java linux
    [root@server ~]# echo ${#asso_array1[*]}
    3
    [root@server ~]# echo ${#asso_array2[*]}
    4
    [root@server ~]# echo ${!asso_array2[*]}
    name3 name2 name1 name4
    ​
    ​
    9. 交互式定义变量的值 read    主要用于让用户去定义变量值
    -p 提示信息
    -n 字符数 (限制变量值的字符数)
    -s 不显示   
    -t 超时(默认单位秒)(限制用户输入变量值的超时时间)
    ​
    [root@MissHou shell01]# cat 1.txt 
    10.1.1.1 255.255.255.0
    ​
    [root@MissHou shell01]# read -p "Input your IP and Netmask:" ip mask < 1.txt 
    [root@MissHou shell01]# echo $ip
    10.1.1.1
    [root@MissHou shell01]# echo $mask
    255.255.255.0
    ​
    ​
    10. 其他变量(扩展)
    1)取出一个目录下的目录和文件:dirname和 basename 
    2)变量"内容"的删除和替换
    一个“%”代表从右往左去掉一个/key/
    两个“%%”代表从右往左最大去掉/key/
    一个“#”代表从左往右去掉一个/key/
    两个“##”代表从左往右最大去掉/key/
    ​
    # A=/root/Desktop/shell/mem.txt 
    # echo $A
    /root/Desktop/shell/mem.txt
    # dirname $A   取出目录
    /root/Desktop/shell
    # basename $A  取出文件
    mem.txt
    ​
    # url=www.taobao.com
    # echo ${#url}           获取变量的长度
    # echo ${url#*.}
    # echo ${url##*.}
    # echo ${url%.*}
    # echo ${url%%.*}
    ​
    ++++++++++++++++++++++++++++++++++++++++++++++++++
    以下内容自己完成:
    替换:/ 和 //
     1015  echo ${url/ao/AO}
     1017  echo ${url//ao/AO}   贪婪替换
     
    替代: - 和 :-  +和:+
     1019  echo ${abc-123}
     1020  abc=hello
     1021  echo ${abc-444}
     1022  echo $abc
     1024  abc=
     1025  echo ${abc-222}
    ​
    ${变量名-新的变量值} 或者 ${变量名=新的变量值}
    变量没有被赋值:会使用“新的变量值“ 替代
    变量有被赋值(包括空值): 不会被替代
    ​
     1062  echo ${ABC:-123}
     1063  ABC=HELLO
     1064  echo ${ABC:-123}
     1065  ABC=
     1066  echo ${ABC:-123}
    ​
    ${变量名:-新的变量值} 或者 ${变量名:=新的变量值}
    变量没有被赋值或者赋空值:会使用“新的变量值“ 替代
    变量有被赋值: 不会被替代
    ​
     1116  echo ${abc=123}
     1118  echo ${abc:=123}
    ​
    [root@server ~]# unset abc
    [root@server ~]# echo ${abc:+123}
    ​
    [root@server ~]# abc=hello
    [root@server ~]# echo ${abc:+123}
    123
    [root@server ~]# abc=
    [root@server ~]# echo ${abc:+123}
    ​
    ${变量名+新的变量值}
    变量没有被赋值或者赋空值:不会使用“新的变量值“ 替代
    变量有被赋值: 会被替代
    [root@server ~]# unset abc
    [root@server ~]# echo ${abc+123}
    ​
    [root@server ~]# abc=hello
    [root@server ~]# echo ${abc+123}
    123
    [root@server ~]# abc=
    [root@server ~]# echo ${abc+123}
    123
    ${变量名:+新的变量值}
    变量没有被赋值:不会使用“新的变量值“ 替代
    变量有被赋值(包括空值): 会被替代
    ​
    [root@server ~]# unset abc
    [root@server ~]# echo ${abc?123}
    -bash: abc: 123
    ​
    [root@server ~]# abc=hello
    [root@server ~]# echo ${abc?123}
    hello
    [root@server ~]# abc=
    [root@server ~]# echo ${abc?123}
    ​
    ${变量名?新的变量值}
    变量没有被赋值:提示错误信息
    变量被赋值(包括空值):不会使用“新的变量值“ 替代
    ​
    [root@server ~]# unset abc
    [root@server ~]# echo ${abc:?123}
    -bash: abc: 123
    [root@server ~]# abc=hello
    [root@server ~]# echo ${abc:?123}
    hello
    [root@server ~]# abc=
    [root@server ~]# echo ${abc:?123}
    -bash: abc: 123
    ​
    ${变量名:?新的变量值}
    变量没有被赋值或者赋空值时:提示错误信息
    变量被赋值:不会使用“新的变量值“ 替代
    ​
    说明:?主要是当变量没有赋值提示错误信息的,没有赋值功能

    ##简单的四则运算

    算术运算:默认情况下,shell就只能支持简单的==整数==运算

    + - * /  %(取模,求余数) 
    Bash shell 的算术运算有四种方式:
    1. 使用 $(( ))
    2. 使用$[ ]
    3. 使用 expr 外部程式
    4. 使用let 命令
    ​
    注意:
    n=1
    let n+=1  等价于let n=n+1
    ​
    ​
    ​
    思考:能不能用shell做小数运算?
    [root@server shell01]# echo 1+1.5|bc
    2.5
    ​
    ​
    i++ 和 ++i (了解)
    对变量的值的影响:
    [root@node1 ~]# i=1
    [root@node1 ~]# let i++
    [root@node1 ~]# echo $i
    2
    [root@node1 ~]# j=1
    [root@node1 ~]# let ++j
    [root@node1 ~]# echo $j
    2
    ​
    对表达式的值的影响:
    [root@node1 ~]# unset i j
    [root@node1 ~]# i=1;j=1
    [root@node1 ~]# let x=i++         先赋值,再运算
    [root@node1 ~]# let y=++j         先运算,再赋值
    [root@node1 ~]# echo $i
    2
    [root@node1 ~]# echo $j
    2
    [root@node1 ~]# echo $x
    1
    [root@node1 ~]# echo $y
    2
    ​
    ​

    总结:

    $(())  $[]
    expr 注意空格,*要进行转义 \
    ​
    let n+=1  等价   let n=n+1
    let n=n**5      n有初值,然后求次幂
    ​
    i++ ++i 
    对变量本身没有影响(自己+1);
    表达式中有影响;i++ 先赋值再运算  ++i先运算再赋值
    let x=i++   let x=++i
    ​

    ##条件判断

    ###1. 语法格式

    • 格式1: ==test== 条件表达式

    • 格式2: [ 条件表达式 ]

    • 格式3: [[ 条件表达式 ]] 支持正则 =~

    说明:

    man test去查看,很多的参数都用来进行条件判断

    ###2. 条件判断相关参数

    • 与文件存在与否的判断

    -e  是否存在   不管是文件还是目录,只要存在,条件就成立
    -f  是否为普通文件
    -d  是否为目录
    -S  socket
    -p  pipe
    -c  character
    -b  block
    -L  软link
    ​
    三种语法格式:
    test -e file                    只要文件存在条件为真
    [ -d /shell01/dir1 ]            判断目录是否存在,存在条件为真
    [ ! -d /shell01/dir1 ]      判断目录是否存在,不存在条件为真
    [[ -f /shell01/1.sh ]]      判断文件是否存在,并且是一个普通的文件
    ​
    -s 判断文件是否有内容(大小),非空文件条件满足
    说明:-s表示非空,! -s 表示空文件
    说明:1.sh文件里有内容的。
    [root@server shell01]# test -s 1.sh
    [root@server shell01]# echo $?
    0
    [root@server shell01]# touch aaa
    [root@server shell01]# cat aaa
    [root@server shell01]# test -s aaa
    [root@server shell01]# echo $?
    1
    [root@server shell01]# test ! -s aaa
    [root@server shell01]# echo $?
    0
    [root@server shell01]# test ! -s 1.sh
    [root@server shell01]# echo $?
    1
    ​
    • 文件权限相关的判断

    -r  当前用户对其是否可读
    -w  当前用户对其是否可写
    -x  当前用户对其是否可执行
    -u  是否有suid
    -g  是否sgid
    -k  是否有t位
    ​
    • 两个文件的比较判断

    file1 -nt  file2    比较file1是否比file2新    
    file1 -ot  file2    比较file1是否比file2旧
    file1 -ef  file2    比较是否为同一个文件,或者用于判断硬连接,是否指向同一个inode
    ​
    test file1 -nt file2    
    [ file1 -ot file2 ]
    • 整数之间的判断

    -eq 相等
    -ne 不等
    -gt 大于
    -lt 小于
    -ge   大于等于
    -le 小于等于
    • 字符串之间的判断

    -z  是否为空字符串         字符串长度为0,就成立
    -n  是否为非空字符串        只要字符串非空,就是成立
    string1 = string2       是否相等
    string1 != string2      不等
    ​
    [root@server shell01]# AAA=hello
    [root@server shell01]# BBB=world
    [root@server shell01]# test -z $AAA
    [root@server shell01]# echo $?
    1
    [root@server shell01]# test -n $AAA
    [root@server shell01]# echo $?
    0
    ​
    [root@server shell01]# [ $AAA = $BBB ]
    [root@server shell01]# echo $?
    1
    [root@server shell01]# [ $AAA != $BBB ]
    [root@server shell01]# echo $?
    0
    ​
    • 多重条件判断

    逻辑判断符号:
     -a     和 &&    (and 逻辑与)       两个条件同时满足,整个大条件为真
     -o     和 ||    (or 逻辑或)            两个条件满足任意一个,整个大条件为真
    ​
     
    [ 1 -eq 1 -a 1 -ne 0 ]              整个表达式为真
    [ 1 -eq 1 ] && [ 1 -ne 0 ]          
    ​
    ​
    [ 1 -eq 1 -o 1 -ne 1 ]              整个表达式为真
    [ 1 -eq 1 ] || [ 1 -ne 1 ]
    ​
    [root@server shell01]# [ 1 -eq 0 ] && echo true || echo false
    false
    [root@server shell01]# [ 1 -eq 1 ] && echo true || echo false
    true
    ​
    &&:前面的表达式为真
    ||:前面的表达式为假
    ​
    ​
    ​
    总结:
    1、; && ||都可以用来分割命令或者表达式
    2、; 完全不考虑前面的语句是否正确执行,都会执行;号后面的内容
    3、&& 需要考虑&&前面的语句的正确性,前面语句正确执行才会执行&&后的内容;反之亦然
    make && make install
    4、|| 需要考虑||前面的语句的非正确性,前面语句执行错误才会执行||后的内容;反之亦然
    5、如果&&和||一起出现,从左往右依次看,按照以上原则
    ​
    ​

    ###3. 示例

    示例:
    数值比较:
    [root@server ~]# [ $(id -u) -eq 0 ] && echo "the user is admin"
    [root@server ~]$ [ $(id -u) -ne 0 ] && echo "the user is not admin"
    [root@server ~]$ [ $(id -u) -eq 0 ] && echo "the user is admin" || echo "the user is not admin"
    ​
    [root@server ~]# uid=`id -u`
    [root@server ~]# test $uid -eq 0 && echo this is admin
    this is admin
    [root@server ~]# [ $(id -u) -ne 0 ]  || echo this is admin
    this is admin
    [root@server ~]# [ $(id -u) -eq 0 ]  && echo this is admin || echo this is not admin
    this is admin
    [root@server ~]# su - stu1
    [stu1@server ~]$ [ $(id -u) -eq 0 ]  && echo this is admin || echo this is not admin
    this is not admin
    [stu1@server ~]$ 
    ​
    ​
    类C风格的数值比较:
    注意:在(( ))中,=表示赋值;==表示判断
     1159  ((1==2));echo $?
     1160  ((1<2));echo $?
     1161  ((2>=1));echo $?
     1162  ((2!=1));echo $?
     1163  ((`id -u`==0));echo $?
     
     1209  ((a=123));echo $a
     1210  unset a
     1211  ((a==123));echo $?
     
    ​
    ​
    字符串比较:
    注意:双引号引起来,看作一个整体;= 和 == 在 [ 字符串 ] 比较中都表示判断
     1196  a='hello world';b=world
     1197  [ $a = $b ];echo $?
     1198  [ "$a" = "$b" ];echo $?
     1199  [ "$a" != "$b" ];echo $?
     1200  [ "$a" !== "$b" ];echo $?        错误
     1201  [ "$a" == "$b" ];echo $?
     1202  test "$a" != "$b";echo $?
    ​
    ​
    ​
    思考:[ ] 和 [[ ]] 有什么区别?
    ​
     1213  a=
     1214  test -z $a;echo $?
     1215  a=hello
     1216  test -z $a;echo $?
     1217  test -n $a;echo $?
     1217  test -n "$a";echo $?
    ​
    # [ '' = $a ];echo $?
    -bash: [: : unary operator expected
    2
    # [[ '' = $a ]];echo $?
    0
    ​
    ​
     1278  [ 1 -eq 0 -a 1 -ne 0 ];echo $?
     1279  [ 1 -eq 0 && 1 -ne 0 ];echo $?
     1280  [[ 1 -eq 0 && 1 -ne 0 ]];echo $?
    ​
    ​

    4. 总结

    难学

  • 相关阅读:
    Vue 3.0前的 TypeScript 最佳入门实践
    DHCP服务器的部署使用
    python基于PHP+MySQL的超市管理系统
    EL表达式 Jstl (附上代码理解)
    除法类型复合指标异动贡献度计算
    [附源码]java毕业设计青少年计算机知识学习系统
    Kaggle比赛:成人人口收入分类
    GIS前端—Popup标注视图
    牛客网基础知识强化巩固-周结02
    【LeetCode-中等题】27. 移除元素
  • 原文地址:https://blog.csdn.net/qq_57747969/article/details/134446867