高级变量分为三类

变量扩展  ${变量名}                  例   ${filename}   大括号

命令替换  $(命令)        $(ls /)    小括号

算术扩展  $((算数式))      $((9+9))    小括号

 (一) 变量扩展:测试存在性及空值

测试变量   是否存在的   基本用法

${待测变量-默认值}   如果该变量不存在,则赋值默认值。如果该变量存在,则显示变量值

  1. [root@localhost ShellScript]# echo $From          #利用上一章中的变量来测试
  2. From: me@example.edu.cn
  3. [root@localhost ShellScript]# r=${From-noAddress}
  4. [root@localhost ShellScript]# echo $r            #变量存在,则将变量值赋值给r
  5. From: me@example.edu.cn
  6. [root@localhost ShellScript]# unset From          #清楚该变量
  7. [root@localhost ShellScript]# echo $r
  8. From: me@example.edu.cn
  9. [root@localhost ShellScript]# r=${From-noAddress}    #重新判断赋值
  10. [root@localhost ShellScript]# echo $r     #打印默认值 noAddress
  11. noAddress

这里有个注意的点。就是   变量存在与变量值为空的问题。${变量名-默认值}只会在变量不存在的时候,显示默认值,而如果存在该变量,但变量值为空的话,则会显示空,而非默认值。

如果要将变量存在于变量值为空同时判断的话,则需要在-前面加一个:,才能在变量为空或变量值为空的时候显示默认值

${变量名:-默认值}

  1. [root@localhost ShellScript]# From=                #将该变量值设为空
  2. [root@localhost ShellScript]# r=${From-noAddress}        #赋值
  3. [root@localhost ShellScript]# echo $r               #可以发现,采用-赋值,他不会将默认值赋值给r,而会将空赋给r,打印如下   
  4.  
  5. [root@localhost ShellScript]# r=${From:-noAddress}        #若想让变量显示默认值,则需要在-之前加上:,才能显示默认值,打印如下
  6. [root@localhost ShellScript]# echo $r
  7. noAddress

这一点,在写脚本赋值默认参数的时候,很实用。因为,很多时候,需要给脚本赋值,但是如果客户不赋值的话,一般会给一个默认值。就可以采用这种方式来操作

例:

  1. [root@localhost ShellScript]# vim testmsg.sh
  2. #! /bin/bash
  3. filename=$
  4. MSG=${filename:-"testmsg.txt"}
  5. cat > $MSG <<here
  6. From: im@example.edu.cn
  7. To : yr@example.edu.cn
  8. Subject:测试一下
  9.  
  10. 这是一封信,请勿回复
  11. here
  12.  
  13. ~
  14. ~
  15. ~
  16. ~
  17. ~
  18. ~
  19. ~
  20. ~
  21. ~
  22. ~
  23. ~
  24. "testmsg.sh" [新] 12L, 184C 已写入
  25. [root@localhost ShellScript]# sh testmsg.sh #不赋值的时候,显示的是默认值testmsg.txt ls打印一下,看看是否存在该文件,cat一下,看看文件内容是否正确
  26. [root@localhost ShellScript]# ls
  27. .txt create_prg.sh hello hello.c testmsg.sh testmsg.txt
  28. [root@localhost ShellScript]# cat testmsg.txt
  29. From: im@example.edu.cn
  30. To : yr@example.edu.cn
  31. Subject:测试一下
  32.  
  33. 这是一封信,请勿回复
  34. [root@localhost ShellScript]# sh testmsg.sh testmsg2.txt  #赋值的时候,显示的是赋值之后的testmsg2.txt,ls并cat一下查验,证明脚本没有任何问题
  35. [root@localhost ShellScript]# ls
  36. .txt hello testmsg2.txt testmsg.txt
  37. create_prg.sh hello.c testmsg.sh
  38. [root@localhost ShellScript]# cat testmsg2.txt
  39. From: im@example.edu.cn
  40. To : yr@example.edu.cn
  41. Subject:测试一下
  42.  
  43. 这是一封信,请勿回复

特殊运用法

[ -n ${DEBUG:-} ] && set -v

该条语句一般用在script的开头,用来排错

注:

[ ] 是测试条件的语法  -n  来测试后接的变量是否有值     即  测不空   若非空,则传回真值

&&之前的半句的意思就很清楚了。如果DEBUG为空,则默认值为空,则 -n 整个都为空值

如果DEBUG不为空,则[-n] 不为空,则会执行后一句  set -v 来查错

OK.这个命令,我操作之后,无论如何都会执行后面的  set -v  很纳闷,这个地方留意下,以后再补充,有可能我写的不对

  1. [root@localhost ShellScript]# vim testmsg.sh
  2. DEBUG="debug"
  3. echo $DEBUG
  4. echo
  5.  
  6. #[ -n ${DEBUG:-} ] && set -v              这里无论DEBUG是否为空,都会执行,很纳闷
  7. [ -n ${DEBUG:- } ] && echo hehe
  8. echo $hehe
  9. #! /bin/bash
  10. filename=$
  11. MSG=${filename:-"testmsg.txt"}
  12. cat > $MSG <<here
  13. From: im@example.edu.cn
  14. To : yr@example.edu.cn
  15. Subject:测试一下
  16.  
  17. 这是一封信,请勿回复
  18. here
  19.  
  20. ~
  21. ~
  22. ~

OK.昨天测试的上述脚本,后面的set -v总是会进行打印,弄的我束手无策,去百度搜了一下,也没有什么进展,问了一下群里的朋友,群里的朋友说不能这么写,有点不信邪吧。。。呵呵,因为逻辑没错误的东西我一般都不大信邪

今早来,又试了一下,这次我将${DEBUG:-}赋值给了一个变量,用[ -n ]来判断看看结果。结果依然。。。。。我在想,难道真如那位朋友所说,[ -n ]只能用于If 而不能用 && 链接?太扯淡了吧。。。继续百度搜了一下资料,突然在一篇文章中,我发现了一个新奇的东东

如下图

发现跟我代码的区别了么?他在-n 后面的变量,使用双引号引起来的,而我却没有用双引号,而  $[DEBUG:-]其实本身也是一种高级变量的形式。那是否我也应该用双引号来引起来呢?果然问题出在这里

  1. #DEBUG="debug"
  2. #echo $DEBUG
  3. #echo
  4. #isDebug=${DEBUG:-}
  5. [ -n "${DEBUG:-}" ] && set -v #双引号将变量括起来,才能让 -n 起作用
  6. #[ -n "$isDebug" ] && echo hehe
  7. #echo $hehe
  8. #! /bin/bash
  9. filename=$
  10. MSG=${filename:-"testmsg.txt"}
  11. cat > $MSG <<here
  12. From: im@example.edu.cn
  13. To : yr@example.edu.cn
  14. Subject:测试一下
  15.  
  16. 这是一封信,请勿回复
  17. here

 测试变量 “不存在”  或其值为空:则给空变量赋默认值

  1. [root@localhost ShellScript]# unset count
  2. [root@localhost ShellScript]# r=${count:=}
  3. [root@localhost ShellScript]# echo $count
  4.  
  5. [root@localhost ShellScript]# echo $r

从上例可以看出,r 和 count的值均赋值为了100

这个例子的用法在于,给变量一个初始值。也就是给count一个初始值来做操作

例如上上个例子的filename=$1中,是通过   MSG=${filename:-"testmsg.txt"}来给MSG赋值并操作的。那filename的值还是为空的。如果要将filename的默认值也设置为testmsg.txt则可以用MSG=${filename:="testmsg.txt"} 来操作执行

测试变量是否 "不存在" 或其值为空:提示错误信息,并终止脚本程序运行

语法为  ${待测变量:?提示信息}

类似于 if [ 变量不存在 或 空值 ]; then

  显示变量名称: '提示信息'

  else

    继续执行下面的命令

  fi

注意,就如上面的拆解所展示的一样,如果该变量为空,只会显示错误信息,而停止执行整个脚本程序。

这个我觉得也很好用

  1. [root@localhost ShellScript]# vim fn.sh
  2. #! /bin/bash
  3. filename=${:?“请输入要删除的路径”}
  4. echo "你要删除的目录指令为:"
  5. echo "rm -f $filename"
  6. ~
  7. ~
  8. ~
  9. ~
  10. ~
  11. "fn.sh" 4L, 124C 已写入
  12. [root@localhost ShellScript]# sh fn.sh
  13. fn.sh:行2: : “请输入要删除的路径”
  14. [root@localhost ShellScript]# sh fn.sh testmsg.txt
  15. 你要删除的目录指令为:
  16. rm -f testmsg.txt

这样就能避免误删除操作

测试变量的存在性

语法  ${待测变量:+真值}

判断条件:若变量存在且值非空,符合判断

  1. IamHappy="Feel so good"
  2. r=${IamHappy:+'true'} #IamHappy该变量存在且非空,所以r变量的值应为true
  3. echo $r

用途:用来测试某件事的真伪

  1. [root@localhost ShellScript]# vim fgrep.sh
  2. #! /bin/bash
  3.  
  4. exec grep -F ${:+"$@"}
  5. ~
  6. ~
  7. "fgrep.sh" [新] 3L, 38C 已写入
  8. [root@localhost ShellScript]# sh fgrep.sh Mem /proc/meminfo /root/test.txt
  9. /proc/meminfo:MemTotal: kB
  10. /proc/meminfo:MemFree: kB
  11. /proc/meminfo:MemAvailable: kB
  12. grep: /root/test.txt: 没有那个文件或目录

上例中有两个点,一个是${:+}的语法,记得后面的变量也好,值也好都要加引号。

在一个就是$@,估计大家会有点懵。。。没关系,找一下我以前的文章,在鸟哥那本书的介绍中,有这个介绍。总结一下

  1. $0: 脚本本身文件名称
  2. $1: 命令行第一个参数,$2为第二个,以此类推
  3. $*: 所有参数列表
  4. $@: 所有参数列表
  5. $#: 参数个数
  6. $$: 脚本运行时的PID
  7. $?: 脚本退出码
  8.  
  9. ∗与@的区别
  10.  
  11. 当命令行为test.sh 1 2 3
  12. "$*“表示"1 2 3
  13. "$@“表示"1 2 3
  14. 二者没有被引号括起来时是一样的都为"1 2 3",只有当被引号括起来后才表现出差异
  15.  
  16. 总结以上高级用法的应用。我就不写了,贴个图以示留念

 (二)变量扩展:取字符串切片,字符串长度。也就是所谓的截取字符串

1  从某一位置开始到末尾截取

语法一   ${变量:位置起点}有指定的位置开始,截取字符串到末尾

  1. [root@localhost ShellScript]# myname="Shell man"
  2. [root@localhost ShellScript]# substr=${myname:}
  3. [root@localhost ShellScript]# echo $substr
  4. l man

语法二:${变量:位置起点:长度}

例子中继续沿用上面的myname

  1. [root@localhost ShellScript]# substr=${myname::}
  2.  
  3. [root@localhost ShellScript]# echo $substr
  4. l ma
  1. #检验IFS分隔符参数
  2. [root@localhost ShellScript]# echo "_${IFS:1:1}_" #第二个参数tab
  3. _ _
  4. [root@localhost ShellScript]# echo "_${IFS:2:1}_" #第三个参数换行
  5. _
  6. _
  7. [root@localhost ShellScript]# echo "_${IFS:0:1}_" #第一个参数空格
  8. _ _

取部分位置参数

这里用参数变量来举例子,即命令行参数

${@:起点}

有起点开始,取得后面所有未知的参数

解析:

命令行参数第一个用$1,第二个用$2表示,以此类推。$@表示所有参数,在上节中有专门做过介绍。$0则表示命令本身。像$0,$1,$2,$3则成为位置参数

${@:起点:个数}

从起点开始,取得个数个位置参数的值

例:

  1. [root@localhost ShellScript]# vim poz.sh
  2. #! /bin/bash
  3. echo ${@:} #从第一个参数起,取出所有剩余参数
  4. echo ${@::} #从第一个参数起,取出两个参数
  5.  
  6. ~
  7. "poz.sh" [新] 4L, 40C 已写入
  8. [root@localhost ShellScript]# sh poz.sh

计算字符串长度

语法 ${#变量}

  1. [root@localhost ShellScript]# filename="/usr/sbin/ntpdate"
  2. [root@localhost ShellScript]# echo ${#filename}

总结:

其他方法:

借助外部程序expr来计算

通过expr的length选项来计算

  1. str="Here you are"
  2. len=$(expr length "$str")
  3. echo $len
    lenT=$(expr "$str" : '.*')
    echo $lenT

expr “字符串” : '.*'

:后接的.*是一个代表任意多个字符的字符串样式,expr会根据此样式来对比"字符串",等于是计算字符串长度。

  1. str='Here you are'
  2. len=$(expr "$str" : '.*')
  3. echo "str字符串长度为:$len"

三   变量扩展: 对比样式

解析:所谓对比样式,目的是截取变量值(字符串)的某一部分,做法是:将符合样式的部分字符串删除或取代。

1  有字符串前面对比,删除相符者

语法 :${变量#样式}

解析:由前面(最左边)开始,对比变量值,删除“最短相符合的字符串”

  1. [root@localhost ~]# filename="/usr/sbin/ntpdate"
  2. [root@localhost ~]# r=${filename#/*/}
  3. [root@localhost ~]# echo $r
  4. sbin/ntpdate
  5. [root@localhost ~]# r=${filename#*/}
  6. [root@localhost ~]# echo $r
  7. usr/sbin/ntpdate
  8. [root@localhost ~]# r=${filename#/*}#这个地方我不太理解,因为/*/这个我理解,表示两个斜杠之间有内容或为空字符串都会被删掉。那我/*是会删除/usr还是/后面的所有部分呢?结果是只把/删除了。。。。
  9. [root@localhost ~]# echo $r
  10. usr/sbin/ntpdate
  11. [root@localhost ~]# r=
  12. [root@localhost ~]# echo $r
  13.  
  14. [root@localhost ~]# r=${filename#/*}
  15. [root@localhost ~]# echo $r
  16. usr/sbin/ntpdate
  17. [root@localhost ~]# r=${filename#/usr}
  18. [root@localhost ~]# echo $r
  19. /sbin/ntpdate
  20. [root@localhost ~]# r=${filename#/usr/sbin/}
  21. [root@localhost ~]# echo $r
  22. ntpdate

由前面比对,删除最长的

语法:${变量##样式}

解析:由前面最左边开始,对比变量值,删除"最长相符合的字符串"

好麻烦,还是给个例子把这一块全部归拢一下吧。一下摘录  摘抄地址:https://www.cnblogs.com/wqbin/p/11597700.html

  1. 假设我们定义了一个变量为:
  2.  
  3. file=/dir1/dir2/dir3/my.file.txt
  4.  
  5. 我们可以用${ }分别替换获得不同的值:
  6.  
  7. ${file#*/}:拿掉第一条/及其左边的字串:dir1/dir2/dir3/my.file.txt
  8. ${file##*/}:拿掉最后一条/及其左边的字串:my.file.txt
  9. ${file#*.}:拿掉第一个.及其左边的字串:file.txt
  10. ${file##*.}:拿掉最后一个.及其左边的字串:txt
  11. ${file%/*}:拿掉最后条/及其右边的字串:/dir1/dir2/dir3
  12. ${file%%/*}:拿掉第一条/及其右边的字串:(空值)
  13. ${file%.*}:拿掉最后一个.及其右边的字串:/dir1/dir2/dir3/my.file
  14. ${file%%.*}:拿掉第一个.及其右边的字串:/dir1/dir2/dir3/my

注解:

#是去掉左边 (在键盘上#在${}之左边)

%是去掉右边(在键盘上%在${}之右边)

#   % %:从左边数第一条,从右边数最后一条

## % :   从右边数第一条,从左边数最后一条

将这一套全部解释透了。

总结:

取代或删除部分字符串

只替换第一个对比符合的字符串

语法:${变量/样式/替换字符串}

替换全部符合的字符串

语法:${变量//样式/替换字符串}

注意,这里是不转义的。也就是不能用转义字符来转义,而是通过单引号来区分。例

  1. [root@localhost ~]# echo $filename #假设我要将/换成,
  2. /usr/sbin/ntpdate
  3. [root@localhost ~]# r=${filename////,} #开始的时候我采用的转义字符,//来表示/。结果,他会将//认成全部替换,剩余依然。
  4. [root@localhost ~]# echo $r
  5. ,usr,sbin,ntpdate
  6. [root@localhost ~]# r=${filename///,} #继续测试,皆以失败告终
  7. [root@localhost ~]# echo $r
  8. /usr/sbin/ntpdate
  9. [root@localhost ~]# r=${filename/ //,}
  10. [root@localhost ~]# echo $r
  11. /usr/sbin/ntpdate
  12. [root@localhost ~]# r=${filename/ ///,}
  13. [root@localhost ~]# echo $r
  14. /usr/sbin/ntpdate
  15. [root@localhost ~]# r=${filename////,}
  16. [root@localhost ~]# echo $r
  17. ,usr,sbin,ntpdate
  18. [root@localhost ~]# r=${filename/// /,}
  19. [root@localhost ~]# echo $r
  20. /usr/sbin/ntpdate
  21. [root@localhost ~]# r=${filename/'/'/,} #最后突然想用一下引号试试,结果成功。。。。
  22. [root@localhost ~]# echo $r
  23. ,usr/sbin/ntpdate

把对比符合的字符串删除

只删一个

语法:${变量/样式/}

删除第一个符合样式的字符串,这里我理解的是,将符合条件的内容替换成空,即为删除

要求匹配的条件在句首或者句尾

匹配条件时,如果样式前加#,则该条件的要求要出现在变量值的开头才匹配

      如果样式前加%,则该条件要出现在变量值的末尾才匹配

总结:

 四   变量扩展:取变量名列表,数组索引列表

1   取变量名列表

语法:${!开头字符串@}或${!开头字符串*}

解析:把所有以制定字符串开头的变量名列出,用$IFS定义的第一个分隔符隔开。通常为  空格

  1. [root@localhost ~]# echo ${!r@}
  2. r
  3. [root@localhost ~]# rr=
  4. [root@localhost ~]# echo ${!r@}
  5. r rr

2  取数组索引

语法:${!数组变量[@]}或${!数组变量[*]}  这两个语法尊选   @和*的区别

解析:把数组变量所有的索引列出,各索引值之间,用$IFS定义第一个分隔字符。通常为 空格

五   命令替换

命令替换含义:是将命令执行后的标准输出放入变量中的功能。

语法:  变量名称=$(命令)

  1. [root@localhost ~]# filename="/etc/passwd"
  2. [root@localhost ~]# IFS=' '
  3. [root@localhost ~]# r=$(cat $filename)
  4. [root@localhost ~]# echo $r
  5. root:x:::root:/root:/bin/bash
  6. bin:x:::bin:/bin:/sbin/nologin
  7. daemon:x:::daemon:/sbin:/sbin/nologin
  8. adm:x:::adm:/var/adm:/sbin/nologin
  9. lp:x:::lp:/var/spool/lpd:/sbin/nologin
  10. sync:x:::sync:/sbin:/bin/sync
  11. shutdown:x:::shutdown:/sbin:/sbin/shutdown
  12. halt:x:::halt:/sbin:/sbin/halt

多道命令:命令中间用  ;  号隔开,命令替换的值是最后一道指令执行的结果

  1. [root@localhost ~]# PDIR=$(cd ..;pwd) #cd会执行,但是会将pwd的结果放到变量中
  2. [root@localhost ~]# echo $PDIR
  3. /
  4. [root@localhost ~]# pwd
  5. /root

命令替换中,可以包含其他命令替换

  1. [root@localhost ~]# r=$(du -s $(cd ShellScript;pwd))
  2. [root@localhost ~]# echo $r
  3. /root/ShellScript
  1. [root@localhost ShellScript]# vim getipl.sh
  2. #取得IP地址
  3. #! /bin/bash
  4. tmp=$(ifconfig ens33 | grep 'inet')
  5. r=${tmp/inet /}
  6. ip=${r/ netmask*/}
  7. echo $ip
  8. ~
  9. ~
  10. "getipl.sh" 5L, 93C 已写入
  11. [root@localhost ShellScript]# sh getipl.sh
  12. 192.168.132.16

六  算术扩展

缘由:BASH中,变量没有数据类型,会将所有变量值以字符串的形式保存下来。因此任何关于运算的内容,都会原封不动按照字符串的形式显示出来。所以才出现了算术扩展的形式

语法:$((变量A+变量B))

  1. [root@localhost ShellScript]# r=$((+))
  2. [root@localhost ShellScript]# echo $r

六 BASH 高级变量的更多相关文章

  1. Linux Shell 高级变量及字符串

    高级变量包含三个部分1.变量扩展2.命令替换3.算术扩展在Bash Shell中,$算符会触发到上述三种扩展,基本形式如下:    基本型             扩展种类            例子 ...

  2. shell脚本-高级变量

    shell脚本-高级变量 字符串变量切片 ${#var}: 返回字符串变量var的长度 ${var:offset}: 返回字符串变量var中从第offset个字符后(不包括第offset 个字符)的字 ...

  3. [转帖]linux bash环境变量简单总结

    linux bash环境变量简单总结 来源链接:http://www.178linux.com/8005 原创文章,如有转载,请注明原文地址 需要简单学习一下. 其实 我都是直接放一个 .sh文件到 ...

  4. bash环境变量读取顺序

    bash环境变量读取顺序: 交互式登录的用户: /etc/profile --> /etc/profile.d/*.sh --> ~/.bash_profile --> ~/.bas ...

  5. Linux高级变量

    http://blog.chinaunix.net/uid-27040051-id-3450991.html 高级变量 基本形式 [1].变量扩展 格式 ${变量名称} [2].命令扩展 格式 $(命 ...

  6. python笔记:#013#高级变量类型

    高级变量类型 目标 列表 元组 字典 字符串 公共方法 变量高级 知识点回顾 Python 中数据类型可以分为 数字型 和 非数字型 数字型 整型 (int) 浮点型(float) 布尔型(bool) ...

  7. Python中的高级变量类型

    高级变量类型 目标 列表 元组 字典 字符串 公共方法 变量高级 知识点回顾 Python 中数据类型可以分为 数字型 和 非数字型 数字型 整型 (int) 浮点型(float) 布尔型(bool) ...

  8. python高级变量类型(元组,列表,字典, 字符串和重要方法)

    高级变量类型 目标 列表 元组 字典 字符串 公共方法 变量高级 知识点回顾 Python 中数据类型可以分为 数字型 和 非数字型 数字型 整型 (int) 浮点型(float) 布尔型(bool) ...

  9. 第六章 高级I/O函数

    第六章 高级I/O函数 6.1 pipe函数 即管道函数,用于进程间的通信. #include<unistd.h> int pipe(int fd[2]); // fd:filedes / ...

随机推荐

  1. RMQ Direct

    原创转载请注明出处:https://www.cnblogs.com/agilestyle/p/11792398.html RMQ Direct Project Directory Maven Depe ...

  2. Xcode模拟器快捷键

    command + 左右 = 横竖屏旋转 command + H + H = 切入层级后台模式

  3. php substr_count()函数 语法

    php substr_count()函数 语法 作用:统计一个字符串,在另一个字符串中出现次数大理石量具 语法:substr_count(string,substring,start,length) ...

  4. 【CF1253A】Single Push【模拟】

    题意:给你两个数组a,b,求是否存在操作使得a变成b,操作为选取一段子区间[l,r],选一个正整数k,使得ai+=k,i∈[l,r],只能操作一次 题解:模拟即可 #include<iostre ...

  5. 0XFF

    0xFF = 00000000000000000000000011111111 也就是说 0xFF 代表了一个 byte 位全为 1,-1的补码(数据). 数值和数据是两个不同的概念.数值表示一个数的 ...

  6. 2019ICPC上海网络赛A 边分治+线段树

    题目: 给定一棵树, 带边权. 现在有2种操作: 1.修改第i条边的权值. 2.询问u到其他一个任意点的最大距离是多少. 解法:边分治+线段树 首先我们将所有的点修改和边修改都存在对应的边里面. 然后 ...

  7. Flask学习 1创建第一个页面

    #!/usr/bin/env python # encoding: utf-8 """ @version: v1.0 @author: cxa @file: hello. ...

  8. xpath进阶

    目标: 抓取页面列表信息,并且获取第四个单元格得指定属性 代码: import requests from lxml import etree resp = requests.get('http:// ...

  9. quick BI 修改列名备注

    有些列名太长了,所以造成些影响.注意修改即可.

  10. Android -ui控件

    一:TextView控件 TextView --> View 1.创建TextView的两种方式: 1.1编写TextView类 TextView tv = new TextView(this) ...