Shell学习笔记(6)-高级变量之变量扩展

来源:互联网 发布:知乎 马小婷 编辑:程序博客网 时间:2024/05/29 11:47
高级变量,有3个主题:
    变量扩展 ${变量名称}
    命令替换 $(命令)
    算术扩展 $((算术扩式))

变量扩展
"变量存在“的定义
    如果变量曾设值过,则称该变量存在;反之,不曾设值过,或曾用unset取消变量,则称变量不存在或未定义。
    变量设值有两种情况:其值为"非空",与其值为"空"两种。如下所示:
    myname='Basher' 此时变量myname的值非空。
    myname= 此时变量myname的值为空,其值以null表示。
    以上两种情况,表示变量myname是存在的,或变量myname有定义;但若用unset把myname取消,则变量myname不存在,或称myname没有定义。

    语法规则: ${待测变量-默认值}
    语法含义: 若待测变量不存在,则返回默认值,否则返回待测变量的值
    示例:  unset myname
            r=${myname-'Basher'}
        echo $r

    语法规则: ${待测变量:-默认值}
    语法含义:如果待测变量不存在或其值为空,则返回默认值,否则返回待测变量的值
    示例:   myname=
             r=${myname:-'Basher'}
         echo $r

    特殊用法:
    [ -n "${DEBUG:-}" ] && set -v
    用法说明: [ ]是测试条件是语法,其中,-n是用来测试后接的变量是否有值(测:不空),若非空,则传回真值。${DEBUG:-}就是-n要测试的对象。这里,:-的后面原本应放置默认值的地方却没有任何东西,表示故意要让默认值为空值。
              这样做的目的是:如果变量DEBUG非空值,那么,[-n]条件测试就会成立,接着执行逻辑AND(&&)的下一个指令:set -v,于是,script就进入了查错的模式;如果变量DEBUG没有设定或其值为空,则变量扩展的结果是空值,因此,[ -n ]的条件测试不成立,逻辑AND的下一个指令也就不再执行,查错的功能就没有打开。

    语法规则:${待测变量:=默认值}
    语法含义: 若变量不存在或其值为空,则把待测变量设为"默认值";如果变量存在,则传回变量值。

    语法规则: ${待测变量:?提示信息}
    语法含义:待测变量若“不存在”或其值为空,则提示信息并退出运行
    示例:
    #! /bin/bash
    fn=${1:?'错误!请提供要删除的目录名称!'}
    rm -RF ~/$fn
    备注:这里的1是指输入的第一个参数

    语法规则:${待测变量:+真值}
    语法含义:若变量存在且非空,则传回真值,否则返回空值
    示例1:
    IamHappy='Feel so good.'
    r=${IamHappy:+'true'}
    echo $r  //输出true
    示例2:fgrep.sh
    #! /bin/bash
    exec grep -F ${1+"$@"}
    这里使用exec执行grep程序,-F表示使用一串固定的字符串(可用换行字符分开)作为寻找的样式。其中,${1+"$@"}的意思是说:若$1存在(指定要寻找的关键词),则传回所有的参数$@,这表示fgrep.sh一次可以搜寻多个文件。
    ./fgrep.sh Mem /proc/meminfo /root/test.txt 由于$1=Mem非空,判断成立,因此,${1+"$@"}传回$@,此变量之值等于所有的位置参数组合起来:"Mem /proc/meminfo /root/test.txt",因此,最后exec执行的指令是:
    grep -F Mem /proc/meminfo /root/test.txt 这表示,grep可由后面的两个文件去寻找关键词Mem.

    上面所有这些语法规则中,如果去掉:,则只测试存在性,不测试空值


取字符串切片、字符串长度
        功能介绍: 由指定的位置开始,截取子字符串到字符串结束。
        语法规则: ${变量:位置起点}
        示例:
        myname="Sheller man"
        substr=${myname:4}
        echo $substr    //ler man

        功能介绍:由指定的位置开始,截取指定长度的子字符串。
        语法规则: ${变量:位置起点:长度}
        示例:
        echo "_${IFS:0:1}_"
        echo "_${IFS:1:1}_"
        echo "_${IFS:2:1}_"
        IFS是分隔字符变量,是由"空格符"、"TAB(\t)"、"换行字符(\n)"组成

        位置参数
        命令行第一个参数用$1表示,第二个用$2表示,其他依此类推。$@则代表所有的参数。例如:substr.sh x y z这道指令中,第一个参数就是x,第二个是y,第三个是z。$1的值即为x;$2的值为y;$3的值为z。命令本身用$0表示,其值为substr.sh.
        取得部分位置参数的用法如下:${@:起点} ${@:起点:个数}

        功能介绍:字符串长度
        语法规则:
        (1) ${#变量名称}
        (2) expr length "字符串"
        (3) expr "字符串" : '.*'

        示例:
        (1)filename="/usr/sbin/ntpdate"
        echo ${#filename}
        (2)str='Here you are.'
        len=$(expr length "$str")
        (3)str='Here you are.'
        len=$(expr "$str" : '.*')
        取得数组的长度:${#数组[@]} 或${#数组[*]}


删除子字符串
    功能介绍:由字符串前面对比,删除相符者(前面对比,删最短的)
    语法规则:${变量#样式}
    示例:
    (1) filename="/usr/sbin/ntpdate"
          r=${filename#/*/}
          echo $r
    解释:样式/*/的意思是指:凡一对斜线之间有字符者(空字符串亦可),对比符合,因此输出 sbin/ntpdate


    功能介绍:由前面对比、删最长的相符者
    语法规则: ${变量##样式}
    示例:
    (2) filename="/usr/sbin/ntpdate"
        r=${filename##/*/}
        echo $r  //输出ntpdate

    
    功能介绍:由后面对比,删除最短的相符者
    语法规则:${变量%样式}
    示例:
    (3) filename="/usr/sbin/ntpdate"
        r=${filename%/*}
        echo $r //输出/usr/sbin

    功能介绍:由后面对比,删除最长的
    语法:${变量%%样式}
    示例:
    (4) fqdn="www.tnc.edu.cn"
        m=${fqdn%%.*}
        echo $m   //输出www

替换子字符串
    功能介绍:只替换第一个对比符合的字符串
    语法规则: ${变量/样式/替换字符串}
    示例:
    (5) act="mail:x:8:8:mail:/var/mail:/bin/sh"
        r=${act/:/,}
        echo $r //mail,x:8:8:mail:/var/mail:/bin/sh

    功能介绍:替换全部对比符合的字符串
    语法规则:${变量//样式/替换字符串}
    示例:
    (6) act="mail:x:8:8:mail:/var/mail:/bin/sh"
        r=${act//:/,}
        echo $r //mail,x,8,8,mail,/var/mail,/bin/sh

    功能介绍:删除第一个符合样式的字符串
    语法规则:${变量/样式/}

    功能介绍:删除所有符合样式的字符串
    语法规则:${变量//样式/}

    功能介绍:要求替换的样式在句首或句尾,在对比样式时,若在样式前加上#,如#T,则该样式要出现在变量值的开头才算符合。(%对应句尾)
    示例:
    (7) str="Yes, This is a TITLE."
        r=${str/#T* /}
        echo $r
    解释:此处对比的是位置在句首,T字符后接任意长度的字符,最后以空格结尾的字符串,因$str中无此样式,所以整个str变量值原封不动地返回给r。
    如果把样式修改成${str/T* /},表示样式不一定要位于句首,那么,在$str中就有符合的样式了,删除后,值变为Yes, TITLE.


命令替换
    所谓命令替换,是把命令执行后的标准输出放入变量中。
    示例:
    (1) DIRS=$(ls)
        for f in $DIRS
    do
        echo $f
    done
    (2) file="/etc/passwd"
        IFS=' '
    fc=$(cat $file)
    echo $fc
    分隔字符变量IFS的内容,改用空格符.(IFS的内容原为:空格符、\t和\n).取得/etc/passwd的文件内容。由于IFS改为空格符,所以,变量扩展时,换行字符不会被删除,这样才能保持该文件的内容。
    如果不改设IFS,则passwd的每行会去掉换行字符,变成一个以空格符隔开各行的字符串。fc=$(cat $file)改为fc=$(<$file)的效果是一样的,这是使用转向输入取得文件内容,再扩展成变量内容放入fc中。
    (3) PDIR=$(cd ..; pwd)
    (4) r=$(du -s $(pwd))