linux系统中的变量

一、定义

所谓的变量,就是就是利用一个特定的"名称"(name)来存取一段可以变化的"值"(value),简单说来就是“用一个名称储存一个数值”。

 

二、设定(=)

1. 如何设定变量

在 bash 中,你可以用"=" 来设定或重新定义变量的内容:

name=value

 

2. 规则

在设定变量的时侯,得遵守如下规则:

  • 等号左右两边不能使用字符分隔符(IFS),也应避免使用shell的其他元字符(meta charactor)。
  • 变量名称不能使用 $ 符号。
  • 变量名称的第一个字母不能是数字(number)。
  • 变量名称长度不可超过 256 个字母。
  • 变量名称及变量值之大小写是有区别的(case sensitive)。

 

三、取消设定(unset)

1. 取消变量

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

unset 变量名

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

$ A=
$ unset A

第一行只是将变量 A 设定为"空值"(null value),但第二行则让变量 A 不在存在。虽然用echo命令输出都是一样的结果,但是在变量替换的时候却有着不同的效果。如:

${unknow=new}:若$unknow没有设定(unset),则使用new作为传回值,同时将unknow赋值为new,若unknow为空值或者非空值,则new对传回值与unknow均不影响,因此对于一个变量,它有只仅有三种状态:

  • 非空值(not null)
  • 空值(null)
  • 不设定(unset)

 

四、变量替换

1.普通替换

在命令行中使用者可以使用 $ 符号加上变量名称(除了在用 = 号定义变量名称之外),

将变量值给替换出来,然后再重新组建命令行。

比方:

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

在上面的最后一行命令中,在被执行之前(在输入 CR 字符之前),$符号会对每一个变量作替换处理(将变量值替换出来再重组命令行),最后会得出如下命令行:

ls -la /tmp

若从技术细节来看,shell会依据IFS将command line所输入的文字给拆解为"字段"(word)。然后再针对元字符(meta)先作处理,最后再重组整行command line。这里的 $ 就是 command line 中最经典的 meta 之一了,就是作变量替换的。

 

2. 变量扩充

我们也可利用命令行的变量替换能力来"扩充"(append)变量值:

A=B:C:D
A=$A:E

这样,第一行我们设定 A 的值为 "B:C:D",然后,第二行再将值扩充为 "B:C:D:E" 。上面的扩充范例,我们使用区隔符号(:)来达到扩充目的,要是没有区隔符号的话,如下是有问题的:

A=BCD
A=$AE

因为第二次是将 A 的值继承 $AE 的提换结果,而非 $A 再加 E ﹗要解决此问题,我们可用更严谨的替换处理:

A=BCD
A=${A}E

上例中,我们使用 {} 将变量名称的范围给明确定义出来,如此一来,我们就可以将 A 的变量值从 BCD 给扩充为 BCDE 。

 

3. ${}变量替换

(1)一般情况下,$var 与 ${var} 并没有啥不一样。

但是用${ }会比较精确的界定变量名称的范围,但更高级的用法是用来进行变量替换,假设我们定义了一个变量为:

file=/dir1/dir2/dir3/my.file.txt

我们可以用 ${ } 分别替换获得不同的值:

${file#*/}:拿掉第一条 / 及其左边的字符串:dir1/dir2/dir3/my.file.txt
${file##*/}:拿掉最后一条 / 及其左边的字符串:my.file.txt
${file#*.}:拿掉第一个 .  及其左边的字符串:file.txt
${file##*.}:拿掉最后一个 .  及其左边的字符串:txt
${file%/*}:拿掉最后条 / 及其右边的字符串:/dir1/dir2/dir3
${file%%/*}:拿掉第一条 / 及其右边的字符串:(空值)
${file%.*}:拿掉最后一个 .  及其右边的字符串:/dir1/dir2/dir3/my.file
${file%%.*}:拿掉第一个 .  及其右边的字符串:/dir1/dir2/dir3/my

记忆的方法为:

[list]# 是去掉左边(在键盘上 # 在 $ 之左边)
% 是去掉右边(在键盘上 % 在 $ 之右边)
单一符号是最小匹配﹔两个符号是最大匹配。[/list]
${file:0:5}:提取最左边的 5 个字节:/dir1
${file:5:5}:提取第 5 个字节右边的连续 5 个字节:/dir2

(2) 对变量值里的字符串作替换(接上面的例子):

file=/dir1/dir2/dir3/my.file.txt
${file/dir/path}:将第一个 dir 替换为 path:/path1/dir2/dir3/my.file.txt
${file//dir/path}:将全部 dir 提换为 path:/path1/path2/path3/my.file.txt

(3) 针对不同的变量状态赋值(没设定、空值、非空值)

${file-my.file.txt} :假如 $file 没有设定,则使用 my.file.txt 作传回值。(空值及非空值时不作处理)
${file:-my.file.txt} :假如 $file 没有设定或为空值,则使用 my.file.txt 作传回值。 (非空值时不作处理)
${file+my.file.txt} :假如 $file 设为空值或非空值,均使用 my.file.txt 作传回值。(没设定时不作处理)
${file:+my.file.txt} :若 $file 为非空值,则使用 my.file.txt 作传回值。 (没设定及空值时不作处理)
${file=my.file.txt} :若 $file 没设定,则使用 my.file.txt 作传回值,同时将 $file 赋值为my.file.txt 。 (空值及非空值时不作处理)
${file:=my.file.txt} :若 $file 没设定或为空值,则使用 my.file.txt 作传回值,同时将 $file 赋值为 my.file.txt 。(非空值时不作处理)
${file?my.file.txt} :若 $file 没设定,则将 my.file.txt 输出至 STDERR。 (空值及非空值时不作处理)
${file:?my.file.txt} :若 $file 没设定或为空值,则将 my.file.txt 输出至 STDERR。 (非空值时不作处理)

以上的理解在于,你一定要分清楚unset与null及non-null这三种赋值状态。一般而言,:与null有关,若不带:的话,null不受影响,若带:则连null也受影响。还有哦,${#var}可计算出变量值的长度:

${#file} 可得到 27 ,因为/dir1/dir2/dir3/my.file.txt 刚好是 27 个字节...

(4) 用来处理数组

一般而言,A="a b c def" 这样的变量只是将 $A 替换为一个单一的字符串,但是改为 A=(a b c def) ,则是将 $A 定义为组数...

bash 的组数替换方法可参考如下方法:

${A[@]} 或 ${A[*]} 可得到 a b c def (全部组数)
${A[0]} 可得到 a (第一个组数),${A[1]} 则为第二个组数...
${#A[@]} 或 ${#A[*]} 可得到 4 (全部组数数量)
${#A[0]} 可得到1 (即第一个组数(a)的长度),${#A[3]}可得到 3 (第四个组数(def)的长度) A[3]=xyz 则是将第四个组数重新定义为 xyz ...

 

五、export

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

$ A=B
$ export A
或
$ export A=B

经过 export 输出处理之后,变量 A 就能成为一个环境变量供其后的命令使用。

 

六、参考

1. shell十三问

(完)

posted @ 2016-01-11 15:37  大师兄啊哈  阅读(979)  评论(0编辑  收藏  举报