Chinaunix首页 | 论坛 | 博客
  • 博客访问: 21399
  • 博文数量: 13
  • 博客积分: 325
  • 博客等级: 一等列兵
  • 技术积分: 120
  • 用 户 组: 普通用户
  • 注册时间: 2012-07-28 14:33
文章分类

全部博文(13)

文章存档

2012年(13)

分类: LINUX

2012-10-25 18:16:24

    高级变量主要分为3个部分:变量扩展、命令替换和算术扩展。这些内容是Bash shell script程序设计的重要技巧,也是读懂程序代码的关键,必须熟练(高级必备)。在Bash Shell中,运算符会触发上述3种扩展,基本形式为:

  1. ${变量名称}              #变量扩展            #例如: ${filename} 
  2. $(命令)                #命令替换            #例如: $(ls /)
  3. $((算术式))              #算术扩展            #例如: $((9+9))

1、变量扩展:测试存在性及空值
    
    变量扩展的基本型:${变量名称}
    什么是变量扩展? 变量扩展是一种简易的条件判断,对不同的条件赋予变量不同的替换值。简言之,变量扩展是对基本型加上条件判断,如果条件符合,则进行变量替换,如不符合,也有相应的做法。它其实是一种隐含的“if-then-else”语法。

   (1-1)“变量存在”的定义
    如果变量曾设值过,则称该变量存在;反之,不曾设值过,或曾用unset取消变量,则称变量不存在或未定义。变量设值有两种情况,其值“非空”,和其值“空”(null)两种。如下所示

  1. myname='wsp'                   #变量myname的值非空
  2. yourname=                      #变量yourname值为空,其值以null表示
    以上情况,表示两个变量myname和yourname是存在的,或有定义;但若用unset把它们取消,则它们就不存在,或称做没有定义。

   (1-2)测试变量“存在与否”的基本用法
    语法:${变量名称-默认值}
    释义:若待测变量不存在,则传回-后方的默认值;但若变量存在,就传回变量的值。

  1. unset myname              #用unset取消变量myname,因此myname不存在
  2. r=${myname-'wsp'}         #变量myname不存在,故把“wsp”作为变量扩展结果,传回给r
  3. echo $r                   #显示 wsp

   (1-3)测试变量“不存在”或其值为“空”:传回一个默认值
    语法:${变量名称:-默认值}
    释义:若待测变量不存在或其值为空,则传回:-后方的默认值;但若变量存在,就传回变量的值。

  1. myname=                  #myname存在,但值为空(null)
  2. r=${myname-'wsp'}        #变量myname为空,故把“wsp”作为变量扩展结果,传回给r
  3. echo $r                  #显示 wsp
    小整理:
       >变量扩展的条件式中只有-符号时,则只做“存在性”判断
       >变量扩展的条件式是:-符号时,除了对“存在性”判断,还判断是否为空

     变量扩展式 ${变量名称:-默认值}的主要用途是:在script中,变量一定要有值才行。因此,变量扩展的结果,一定要传回一个非空值(使用变量值或默认值)。另外,该变量扩展也经常会运用在script的开头,例如

  1. [ -n ${DEBUG:-} ] && set -v    # -n 是用来测试后面接的变量是否有值,若非空,则传回真值
  2.                                # :- 后面什么都没放,表示故意要让默认值为空
  3.                                # 如果DEBUG非空,则执行set -v 否则-n就不成立,不执行&&后面

   (1-4)测试变量“不存在”或其值为“空”:给变量设一个默认值
    语法:${变量名称:=默认值}
    释义:若待测变量不存在或其值为空,则把变量设为默认值;但若变量存在,就传回变量的值。
    目的:给变量设一个默认值。

  1. count=                     #count有定义,但是值为空
  2. r=${count:=100}            #count值为空,所以把count的值设为100
  3. echo $count                #显示 100
 
   (1-5)测试变量“不存在”或其值为“空”:提示错误信息
    语法:${变量名称:?提示信息}
    释义:若待测变量不存在或其值为空,则显示变量名和:?后面的提示信息,并立即停止执行script。
    目的:确保某变量值一定要存在。

  1. #!/bin/bash
  2. fn=${1:?'错误!请提供要删除的目录的名称'}     #对命令行传入的第一参数$1做检查,若是空值,
  3.                                           #就显示错误信息,并停止执行该script
  4. echo '你要执行删除目录的指令是:'
  5. echo "rm -Rf ~/$fn"

   (1-6)测试变量的“存在性”
    语法:${变量名称:+真值}
    释义:若待测变量存在且非空,则传回“真值”;否则传回空值。这里的真值,只要是非空字符串或者数字都可以。
    目的:用来测试某事件的真的

  1. IamHappy='Feel so good.'
  2. r=${IamHappy:+'true'}           #变量IamHappy存在且非空,传回字字符串 true
  3. echo $r                         #显示 true


2、变量扩展:取字符串切片、字符串长度

    这里介绍如何运用变量扩展机制,取得字符串的某一部分(称为“切片”或“子字符串”),以及如何取得字符串长度。

   (2-1)取字符串切片
    字符串的第一个字符,编号为0,右邻的字符编号,依次增加1.
    取字符串切片的语法有两种:

    >语法一:${变量:位置起点}
     释义:由指定的位置开始,截取子字符串到字符串结束

  1. myname="Sheller man"
  2. substr=${myname:4}
  3. echo $substr               #显示子字符串:ler man

    >语法二:
${变量:位置起点:长度}
     释义:由指定的位置开始,截取指定长度的子字符串

  1. filename="/etc/apache2"
  2. dir1=${filename:1:3}
  3. echo $dir1                 #显示切片:etc
  (2-2)取部分位置参数
    取得字符串切片的做法,也可以套用到命令行参数。
    这里简单的说一下命令行参数:
    命令行第一个参数用$1表示,第二个用$2表示,其他依次类推。$@则代表左右的参数。例如:substr.sh x y z这个指令中,第一个参数是x,第二个参数是y,第三个参数是z。即$1的值为x,$2的值为y,$3的值为z。命令本身用$0表示,其值为substr.sh。想$0,$1,$3等变量,称为位置参数。
    取得位置参数的用法有以下两式:

      ${@:起点} 和 ${@:起点:个数} 


  1. #!/bin/bash
  2. #poz.sh
  3. echo $0                   #显示命令本身
  4. echo ${@:1}               #由第一个位置参数开始(第0个是$0),取得所有位置参数

  5. #若执行该脚本:./poz.sh first second
  6. #则显示结果为:
  7. #poz.sh
  8. #first second

  (2-3)计算字符串长度
    语法:${#变量名称}
    释义:传回变量值的字符串长度

  1. filename="/usr/sbin/ntpdate"
  2. echo ${#filename}                   #显示字符串长度:17
      除了这种方法外,计算字符串长度,还可以用外部程序expr来做:
    
     >方法一:expr length "字符串"
      说明:这里,length的expr的选项,用来指定要计算字符串长度这个操作

  1. str="How are you."
  2. len=$(expr length "$str")
  3. echo "str字符串的长度是: $len"

     >方法二:expr "字符串":'.*'
      说明:这里,:后接的.*是一个代表任意多个字符的字符串样式,expr会根据此样式来对比“字符串”,等于是计算字符串的长度

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


3、变量扩展:对比样式

     这里所谓“对比样式”,目的是想要截取变量值(字符串)的某一部分,其做法是:将符合样式的部分字符串删除或取代。

   (3-1)由字符串前面对比,删除相符者

    >语法:${变量#样式}
     释义:由前面(最左边)开始,对比变量,删除“最短相符合的字符串”

  1. filename="/usr/sbin/ntpdate"
  2. r=${filename#/*/}          #对比样式是/*/,意思是:凡是一对斜线之间有字符串者(空字符也可以)
  3.                            #则对比符合,因#是表示前面去最短的,对比结果为/usr/,故删去
  4.                            #传回剩下的字符串,并赋给r
  5. echo $r                    #显示结果:sbin/ntpdate

    >语法:${变量##样式}
     释义:由前面(最左边)开始,对比变量,删除“最长相符合的字符串”

  1. filename="/usr/sbin/ntpdate"
  2. r=${filename##/*/}        #对比样式是/*/,意思是:凡是一对斜线之间有字符串者(空字符也可以)
  3.                           #则对比符合,因#是表示前面去最长的,对比结果为/usr/sbin/,故删去
  4.                           #传回剩下的字符串,并赋给r

  5. echo $r                   #显示结果:ntpdate

   (3-2)由字符串后面对比,删除相符者

    >语法:${变量%样式}
     释义:由后面(最右边)开始,对比变量,删除“最短相符合的字符串”

    >语法:${变量%%样式}
     释义:由后面(最右边)开始,对比变量,删除“最长相符合的字符串”

  
   (3-3)取代对比符合的字符串

    >只替换第一个对比符合的字符串
     语法:${变量/样式/替换字符串}
     释义:若变量中,有符合样式的字符串(取最长的),则使用替代字符串予以取代。

    >替换全部对比符合的字符串
     语法:${变量//样式/替换字符串}
     释义:若变量中,有符合样式的字符串(取最长的),则使用替代字符串全部予以取代。

  1. act="mail:x:8:8:mail:/var/mail/:/bin/sh"
  2. r=${act//:/,}        #所有的:替换才,
  3. echo $r              #显示结果:mail,x,8,8,mail,/var/mail,/bin/sh

   (3-4)删除对比符合的字符串

    >只删除第一个对比符合的字符串
     语法:${变量/样式/}
     释义:删除第一个符合样式的字符串

    >删除全部对比符合的字符串
     语法:${变量//样式/}
     释义:删除所有符合样式的字符串

  1. act="mail:x:8:8:mail:/var/mail/:/bin/sh"
  2. r=${act//:/}           #所有的:替换才,
  3. echo $r                #显示结果:mailx88mail/var/mail/bin/sh

   (3-4)要求样式在句首或句尾

    在对比样式时,若在样式前面加上#,则该样式要出现在变量值的开头才算符合。若在样式前面加上%,则该样式需要出现在变量值的最后面才算符合。

  1. str="Yes, This is a TITLE"
  2. r=${str/#T* /}         #$str中不能对比到,句首是T开头的任意长度字符串,匹配失败
  3. echo $r                #显示结果:Yes, This is a TITLE



4、变量扩展:
取变量名称列表、数组索引列表

    (4-1)取变量名称列表
     语法:${!开头字符串@} 或 ${!开头字符串*}
     释义:把所有以指定字符串开头的变量名称列出来,各变量之间,用$IFS定义的第一个分隔字符(通常是空格)隔开。

  1. filename="ntpdate"
  2. dir="/usr/bin"
  3. dir_file="$dir/$filename"
  4. echo ${!di@}             #显示结果:dir dir_file

    (4-1)取出数组索引列表
     语法:${!数组变量[@]} 或 ${!数组变量[*]}
     释义:把数组变量多有的索引列出,各索引值之间,用$IFS定义的第一个分隔字符(通常是空格)隔开。

  1. ar=(a b c xy z)
  2. r=${!ar[@]}
  3. echo $r                 #显示结果:0 1 2 3 4


5、命令替换

    所谓的命令替换,是把命令执行后的标准输入放入变量中。例如说,想查看工作目录中的所有的文件名,可以执行ls命令,但如何把这些文件名存入变量中,供往后的程序代码再利用呢?使用命令替换,可以轻松做到。
    命令替换语法: 变量名称=$(命令)

  1. #!/bin/bash
  2. tmp=$(ifconfig eth0 | grep 'inet addr')   #获取eth0网卡的ip资料
  3. r=${tmp/inet addr:/}                      #删除 inet addr:
  4. ip=${r/ Bacst*/}                          #删除  Bacst及其后面的字符,剩下的就是ip地址
  5. echo $ip                                  #显示ip


6、算术扩展

    先看以下程序片段:

  1. I=8+16
  2. echo $I          #显示结果:8+16
      为什么是8+16这个字符串呢?而不是24? 因为Bash的变量,默认没有数据类型,全部以字符串视之。因此8+16对Bash来说只是个字符串,并不进行算术运算。那在Bash中,如何进行算术运算? 方法很多,这里先介绍算术扩展。
    
     算术扩展语法:$((算术式))

   
  1. I=$((8+16))
  2. echo $I                #显示结果:24




地方
阅读(1339) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~