导言

有人会问,变量有什么好说的。顶多赋值一下,引用一下咯。其实不然,活用变量,用好变量,可以在编程中节省很多不必要的代码,而且,关于变量,诸如变量展开,变量判断等,也是shell编程重要的基本功之一。


SHELL变量
变量(variable)是计算机内存中可存储值的一块空间,变量名就是这块空间的名字,变量一定有一个值,这个值就写在这块内存空间内。
shell是一种弱类型的编程语言,不强制要求声明变量类型,事实上,shell变量类型可看做是字串string或者整数int(其实也没区别)。


变量声明和赋值
赋值的时候注意,=符号两旁没有任何空格。
  1. $ var=some_value                      #默认完成变量的声明和赋值
  2. ----------------------------------------
  3. $ var="some important value"         #需要引号圈引带有空格的字串
  4. ----------------------------------------
  5. $ var1=a var2=b var3=$var1               #同一行完成多变量赋值
  6. $ eval `date -d '1 hours ago' +"MONTH=%Y%m DATE=%Y%m%d HOUR=%H"` #经典案例:同时把MONTH DATE HOUR变量赋值完毕
  7. $ echo $MONTH $DATE $HOUR
  8. 201212 20121208 12


变量的引用
变量名var代表变量本身,$var代表变量值,${var}等价。
特别注意有时候,必须使用${var_name}的形式,不然会有歧义。
  1. $ var=abc
  2. $ echo $var #方法1,输出abc
  3. $ echo ${var} #方法2,等效
  4. $ echo "${var}" #方法3,等效
  5. --------------------------------------
  6. echo $varvar #输出空,找不到varvar变量
  7. echo ${var}var #输出abcvar,注意
  8. --------------------------------------
  9. var_another=$var #完成值引用


关于未定义变量和空变量
shell里面,允许变量为空。空值指变量"不含任何字符",等价于,"变量长度为0"。空值记为null。
当引用一个从未出现的变量时,shell判断为未定义。直到下次赋值前,变量值默认被设为null,即空值。
  1. a=b=2 d=3
  1. $ echo "$a$b$c$d" #c未定义就被引用,此时c值是空
  2. 123
unset(built-in)
unset可以删除变量,重置变量为“未定义”的状态。
For each name, remove the corresponding variable or function
  1. $ m=has_a_name #m赋值
  2. $ unset m #取消m
  3. $ echo $m #null
很少有场景会严格区分"变量未定义"和"已定义但为空"的情况,一般情况下,使用两者并无区别。
但某些情况下,未定义的变量可能会造成一定隐患,比如rm -rf /$DIR,且DIR未定义。

set(built-in)
如果想避免使用未定义变量的话,请在脚本开头加上set -u,即“不使用未定义的变量”。
  1. set -u
  2. x=""             #x是空值,已定义
  3. y=            #y是空值,已定义
  4. echo $x$y$z        #z是未定义,此时z值为空(null)
  5. -bash: z: unbound variable #不允许使用z
  6. -------------------------------------------
  7. unset y
  8. echo $x$y
  9. --bash: y: unbound variable #unset是删除,而非清空。
附:顺便说一句,shell未严格区分未定义和空值的情况,但在其他脚本语言比如perl中,严格把未定义变量看成undef数据类型,空值就是""。


其他
先写些基本的,然后深入谈论变量替换等深入内容。


技巧
  1. eval `date -d '1 hours ago' +"MONTH=%Y%m DATE=%Y%m%d HOUR=%H"` eval和赋值的经典案例:同时把MONTH DATE HOUR变量赋值完毕;
  2. unset用来删除变量,而非清空变量;
  3. set -u 设置后可以防止使用未定义的变量。