Chinaunix首页 | 论坛 | 博客
  • 博客访问: 19270178
  • 博文数量: 7460
  • 博客积分: 10434
  • 博客等级: 上将
  • 技术积分: 78178
  • 用 户 组: 普通用户
  • 注册时间: 2008-03-02 22:54
文章分类

全部博文(7460)

文章存档

2011年(1)

2009年(669)

2008年(6790)

分类:

2008-03-21 16:38:03

这次让我们暂时丢开command line,先来了解一下bash变量(variable)...

所谓的变量,就是就是利用一个特定的"名称"(name)来存取一段可以变化的""(value)

*设定(set)*
bash中,你可以用"="来设定或重新定义变量的内容:
        name=value
在设定变量的时侯,得遵守如下规则:
        *
等号左右两边不能使用区隔符号(IFS),也应避免使用的保留字符(meta charactor)
        *
变量名称不能使用$符号。
        *
变量名称的第一个字母不能是数字(number)
        *
变量名称长度不可超过256个字母。
        *
变量名称及变量值之大小写是有区别的(case sensitive)

如下是一些变量设定时常见的错误:
        A= B       
:不能有IFS
        1A=B       
:不能以数字开头
        $A=B       
:名称不能有$
        a=B       
:这跟a=b是不同的
如下则是可以接受的设定:
        A=" B"       
IFS被关闭了(请参考前面的quoting章节)
        A1=B       
:并非以数字开头
        A=$B       
$可用在变量值内
        This_Is_A_Long_Name=b       
:可用_连接较长的名称或值,且大小写有别。

*变量替换(substitution)*
Shell之所以强大,其中的一个因素是它可以在命令行中对变量作替换(substitution)处理。
在命令行中使用者可以使用$符号加上变量名称(除了在用=号定义变量名称之外)
将变量值给替换出来,然后再重新组建命令行。
比方:

        $ A=ls
        $ B=la
        $ C=/tmp
        $ $A -$B $C

(注意:以上命令行的第一个$shell prompt,并不在命令行之内。)
必需强调的是,我们所提的变量替换,只发生在command line上面。(是的,让我们再回到command line吧﹗)
仔细分析最后那行command line,不难发现在被执行之前(在输入CR字符之前)
$
符号会对每一个变量作替换处理(将变量值替换出来再重组命令行),最后会得出如下命令行:

        ls -la /tmp

还记得第二章我请大家"务必理解"的那两句吗?若你忘了,那我这里再重贴一遍:

若从技术细节来看,shell会依据IFS(Internal Field Seperator)command line所输入的文字给拆解为"字段"(word)
然后再针对特殊字符(meta)先作处理,最后再重组整行command line

这里的$就是command line中最经典的meta之一了,就是作变量替换的﹗
在日常的shell操作中,我们常会使用echo命令来查看特定变量的值,例如:

        $ echo $A -$B $C

我们已学过,echo命令只单纯将其argument送至"标准输出"(STDOUT,通常是我们的荧幕)
所以上面的命令会在荧幕上得到如下结果:

        ls -la /tmp

这是由于echo命令在执行时,会先将$A(ls)$B(la)、跟$C(/tmp)给替换出来的结果。

利用shell对变量的替换处理能力,我们在设定变量时就更为灵活了:
        A=B
        B=$A
这样,B的变量值就可继承A变量"当时"的变量值了。
不过,不要以"数学罗辑"来套用变量的设定,比方说:
        A=B
        B=C
这样并不会让A的变量值变成C
上面是单纯定义了两个不同名称的变量:A  B,它们的值分别是B  C。再如:
        A=B
        B=$A
        A=C
同样也不会让B的值换成C
 
若变量被重复定义的话,则原有旧值将被新值所取代。(这不正是"可变的量"吗?  ^_^)
当我们在设定变量的时侯,请记着这点:
        *用一个名称储存一个数值
仅此而已。

此外,我们也可利用命令行的变量替换能力来"扩充"(append)变量值:
        A=B:C:D
        A=$A:E
这样,第一行我们设定A的值为"B:C:D",然后,第二行再将值扩充为"A:B:C:E"

上面的扩充范例,我们使用区隔符号( : )来达到扩充目的,
要是没有区隔符号的话,如下是有问题的:
        A=BCD
        A=$AE
因为第二次是将A的值继承$AE的提换结果,而非$A再加E
要解决此问题,我们可用更严谨的替换处理:
        A=BCD
        A=${A}E
上例中,我们使用{}将变量名称的范围给明确定义出来,
如此一来,我们就可以将A的变量值从BCD给扩充为BCDE

(
提示:关于${name}事实上还可做到更多的变量处理能力,这些均属于比较进阶的变量处理,现阶段暂时不介绍了,请大家自行参考数据。如CU的贴子:
)

* export *

严格来说,我们在当前shell中所定义的变量,均属于"本地变量"(local variable)
只有经过export命令的"输出"处理,才能成为环境变量(environment variable)

        $ A=B
        $ export A

或:

        $ export A=B

经过export输出处理之后,变量A就能成为一个环境变量供其后的命令使用。
在使用export  的时侯,请别忘记shell在命令行对变量的"替换"(substitution)处理,
比方说:

        $ A=B
        $ B=C
        $ export $A

上面的命令并未将A输出为环境变量,而是将B作输出,
这是因为在这个命令行中,$A会首先被提换出B然后再"塞回"export的参数。

要理解这个export,事实上需要从process的角度来理解才能透彻。
我将于下一章为大家说明process的观念,敬请留意。

*取消变量*

要取消一个变量,在bash中可使用unset命令来处理:

        unset A

export一样,unset命令行也同样会作变量替换(这其实就是shell的功能之一)
因此:

        $ A=B
        $ B=C
        $ unset $A

事实上所取消的变量是B而不是A

此外,变量一旦经过unset取消之后,其结果是将整个变量拿掉,而不仅是取消其变量值。
如下两行其实是很不一样的:

        $ A=
        $ unset A

第一行只是将变量A设定为"空值"(null  value),但第二行则让变量A不在存在。
虽然用眼睛来看,这两种变量状态在如下命令结果中都是一样的:

        $ A=
        $ echo $A

        $ unset A
        $ echo $A

请学员务必能识别null valueunset的本质区别,这在一些进阶的变量处理上是很严格的。
比方说:

        $ str=                #设为null
        $ var=${str=expr}        #
定义var
        $ echo $var
       
        $ echo $str
       
        $ unset str        #
取消
        $ var=${str=expr}        #
定义var
        $ echo $var
        expr
        $ echo $str
        expr

聪明的读者(yes, you!),稍加思考的话,
应该不难发现为何同样的var=${str=expr}nullunset之下的不同吧?
若你看不出来,那可能是如下原因之一:
a.
你太笨了
b.
不了解  var=${str=expr}       这个进阶处理
c.
对本篇说明还没来得及消化吸收
e.
我讲得不好
不知,你选哪个呢?....  ^_^

 

再来解释一下var=${str=expr}

首先,var=$str这个大家都可理解吧。
而接下来的思考方向是,究竟$str这个变量是如下哪一种情况呢:
1) unset
2) null
3) not null
1)
假如是unset,那么var=${str=expr}的结果将是:
var=expr
str=expr
2)
假如是null,那var=${str=expr}的结果是:
var=
str=
3)
假如是not null (比方为xyz ),那var=${str=expr}之结果是:
var=xyz
str=xyz

测试如下:

$ showvar() {

>    var=${str=expr}

>    echo \$var is $var

>    echo \$str is $str

> }

$ unset str

$ showvar

$var is expr

$str is expr

$ str=

$ showvar

$var is

$str is

$ str=xyz

$ showvar

$var is xyz

$str is xyz

 

接下来,再来看看var=${str:=expr}好了:
1) $str
not set
var=expr
str=expr

2) $str
null
var=expr
str=expr

3) $str
not null (str=xyz)
var=xyz
str=xyz

测试如下:

$ showvar() {

> var=${str:=expr}

> echo \$var is $var

> echo \$str is $str

> }

$ unset str

$ showvar

$var is expr

$str is expr

$ str=

$ showvar

$var is expr

$str is expr

$ str=xyz

$ showvar

$var is xyz

$str is xyz


最后比教一下${str=expr}${str:=expr}
*两者在not setnot null都一致
*
但当null值时,${str=expr}会将$var$str都设为null,但${str:=expr}则设为expr

 

从这个再延伸出其它模拟,不防请大家"实作"观查一下有何不同?
var=${str-expr} vs var=${str:-expr}
var=${str+expr} vs var=${str:+expr}
var=${str?expr} vs var=${str:?expr}

 

$ showvar() {

>    var=${str-expr}

>    echo \$var is $var

>    echo \$str is $str

> }

$ unset str

$ showvar

$var is expr

$str is

$ str=

$ showvar

$var is

$str is

$ str=xyz

$ showvar

$var is xyz

$str is xyz

 

$ showvar() {

>    var=${str:-expr}

>    echo \$var is $var

>    echo \$str is $str

> }

$ unset str

$ showvar

$var is expr

$str is

$ str=

$ showvar

$var is expr

$str is

$ str=xyz

$ showvar

$var is xyz

$str is xyz

 

可以看出来${str-expr}${str:-expr}

*两者在$strnot setnot null都一致

*但当null值时,${str-expr}会将$var$str都设为null,但${str:-expr}则将$var设为expr

 

$ showvar() {

>    var=${str+expr}

>    echo \$var is $var

>    echo \$str is $str

> }

$ unset str

$ showvar

$var is

$str is

$ str=

$ showvar

$var is expr

$str is

$ str=xyz

$ showvar

$var is expr

$str is xyz

$ showvar() {

>    var=${str:+expr}

>    echo \$var is $var

>    echo \$str is $str

> }

$ unset str

$ showvar

$var is

$str is

$ str=

$ showvar

$var is

$str is

$ str=xyz

$ showvar

$var is expr

$str is xyz

可以看出来${str+expr}${str:+expr}

*两者在$strnot setnot null都一致

*但当null值时,${str+expr}会将$var$str都设为expr,但${str:+expr}则将$var设为null

 

$ showvar() {

>    var=${str?expr}

>    echo \$var is $var

>    echo \$str is $str

> }

$ unset str

$ showvar

expr

$ str=

$ showvar

$var is

$str is

$ str=xyz

$ showvar

$var is xyz

$str is xyz

$ showvar() {

>    var=${str:?expr}

>    echo \$var is $var

>    echo \$str is $str

> }

$ unset str

$ showvar

expr

$ str=

$ showvar

expr

$ str=xyz

$ showvar

$var is xyz

$str is xyz

可以看出来${str?expr}${str:?expr}

*两者在$strnot setnot null都一致

*但当null值时,${str?expr}会将$var$str都设为null,但${str:?expr}则将$var设为expr

综上所述:

$var=${str=expr}$var=${str:=expr}

$var=${str-expr}$var=${str:-expr}

$var=${str+expr}$var=${str:+expr}
$var=${str?expr}
$var=${str:?expr}

* 两者在 $str not set not null 都一致

* 但当 null 值时不一致


分别描述如下:

$var=${str:-expr}的功能:

str非空的时候var赋值为str,否则(包括not setnull)将var赋值为expr

$var=${str-expr}的功能:

str非空的时候var赋值为str,为空的时候var设置为nullnot set的时候将var赋值为expr

 

$var=${str:=expr}的功能:

str非空的时候var赋值为str,否则(包括not setnull)将varstr均赋值为expr

$var=${str=expr}的功能:

str非空的时候var赋值为str,为空的时候var设置为nullnot set的时候将varstr均赋值为expr

 

$var=${str:?expr}的功能:

str非空的时候var赋值为expr,否则将expr写入标准错误后退出

$var=${str?expr}的功能:

str非空的时候var赋值为expr,为空的时候var设置为nullnot set的时候将expr写入标准错误后退出

 

$var=${str:+expr}的功能:

str非空的时候var赋值为expr,否则将不做任何操作

$var=${str+expr}的功能:

str非空的时候var赋值为expr,为空的时候var设置为exprnot set的时候不做任何操作

 

看来还是带有冒号的简单,只有两种情况:非空和其他,呵呵


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