shell十三问之5:问var=value 在export前后的差在哪?

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

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

1. 变量设定(set)

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

name=value

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

  • 等号左右两边不能使用分隔符号(IFS),也应避免使用shell的保留元字符(meta charactor);
  • 变量的名称(name)不能使用$符号;
  • 变量的名称(name)的首字符不能是数字(number)。
  • 变量的名称(name)的长度不可超过256个字符。
  • 变量的名称(name)及变量的值的大小写是有区别的、敏感的(case sensitive,)

如下是一些变量设定时常见的错误:

A= B #=号前后不能有IFS
1A=B #变量名称不能以数字开头
$A=B #变量的名称里有$
a=B  #这跟a=b是不同的,(这不是错误,提醒windows用户)

如下则是可以接受的设定:

A=" B" #IFS被关闭,参考前面的quoting章节
A1=B   #并非以数字开头
A=$B   #$可用在变量的值内
This_Is_A_Long_Name=b #可用_连接较长的名称或值,且有大小区别;

2. 变量替换(substitution)

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

比方:

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

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

ls -la /tmp

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

Note:

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

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

$ echo $A -$B $C

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

ls -al /tmp

这是由于echo命令在执行时,会先将$A (ls)、$B (la)跟$C (/tmp)给替换出来;
利用shell对变量的替换处理能力,我们在设定变量时就更为灵活了:

A=B
B=$A

这样,B的变量值就可继承A变量"当时"的变量值了。
不过,不要以"数学逻辑"来套用变量的设定,比方说:

A=B
B=C

这样,并不会让A的变量值变成C。再如:

A=B
B=$A
A=C

同样也不会让B的值变成C。

上面是单纯定义了两个不同名称的变量:
A 与 B, 它们的取值分别是C与B。

若变量被重复定义的话,则原有值为新值所取代。(这不正是"可变的量"吗?^_^)
当我们在设定变量的时候,请记住这点:用一个名称存储一个数值, 仅此而已。

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

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

这样, 第一行我们设定A的值为"B:C:D",
然后,第二行再将值扩充为"B:C:D:E"。

上面的扩充的范例,我们使用分隔符号(:)来达到扩充的目的,
要是没有分隔符的话,如下是有问题的:

A=BCD
B=$AE

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

A=BCD
A=${A}E

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

Tips:
关于${name}事实上还可以做到更多的变量处理能力,
这些均属于比较进阶阶段的变量处理,现阶段暂不介绍了,
请大家自行参考资料。

3. 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(进程)的概念,敬请留意。

4. 取消变量(unset)

要取消一个变量,在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 value 与 unset的本质区别,
这在一些进阶的变量处理上是很严格的。

比方说:

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

$ echo $str

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

聪明的读者(yes, you!),稍加思考的话,
应该不难发现为何同样的var=${str=expr}
在str为null与unset之下的不同吧?
若你看不出来,那可能是如下原因之一:

  • 你太笨了
  • 不了解 var=${str=expr} 这个进阶处理
  • 对本篇说明还没有来得及消化吸收
  • 我讲得不好

不知,您选哪个呢?...... ^_^.

如何查看docker镜像里的文件

发布于:1年以前  |  1992次阅读  |  详细内容 »

Shell脚本编程30分钟入门

发布于:1年以前  |  599次阅读  |  详细内容 »

Bash脚本15分钟进阶教程

这里的技术技巧最初是来自谷歌的“Testing on the Toilet” (TOTT)。这里是一个修订和扩增版本。

发布于:1年以前  |  500次阅读  |  详细内容 »

shell十三问之9:$@与$*差在哪?

在shell script中,我们可用$0, $1, $2, $3 ...这样的变量分别提取命令行中的参数部分

发布于:1年以前  |  305次阅读  |  详细内容 »

shell十三问之8: $(())与$()还有${}差在哪?

我们上一章介绍了()与{}的不同,这次让我们扩展一下,看看更多的变化:$()与${}又是啥玩意儿呢?

发布于:1年以前  |  272次阅读  |  详细内容 »

shell十三问之7:()与{}差在哪?

许多时候,我们在shell操作上,需要在一定的条件下执行多个命令,也就是说,要么不执行,要么就全执行,而不是每次依序的判断是否要执行下一个命令。

发布于:1年以前  |  288次阅读  |  详细内容 »

shell十三问之6:exec跟source差在哪?

发布于:1年以前  |  280次阅读  |  详细内容 »

shell十三问之5:问var=value 在export前后的差在哪?

发布于:1年以前  |  280次阅读  |  详细内容 »

shell十三问之4:""(双引号)与''(单引号)差在哪?

发布于:1年以前  |  287次阅读  |  详细内容 »

shell十三问之3:别人echo、你也echo,是问echo知多少?

发布于:1年以前  |  291次阅读  |  详细内容 »

shell十三问之2:shell prompt(PS1)与Carriage Return(CR)关系

发布于:1年以前  |  265次阅读  |  详细内容 »

shell十三问之16:学习总结与原帖目录

发布于:1年以前  |  583次阅读  |  详细内容 »

shell十三问之15: [^ ] 跟[! ]差在哪? (RE: Regular Expression)

发布于:1年以前  |  516次阅读  |  详细内容 »

shell十三问之14: [^ ] 跟[! ]差在哪? (wildcard)

发布于:1年以前  |  560次阅读  |  详细内容 »

shell十三问之13: for what? while与until差在哪?

发布于:1年以前  |  301次阅读  |  详细内容 »

shell十三问之12:你要if还是case呢?

发布于:1年以前  |  509次阅读  |  详细内容 »

shell十三问之11:>与< 差在哪?

发布于:1年以前  |  469次阅读  |  详细内容 »

shell十三问之10:&& 与 || 差在哪?

发布于:1年以前  |  469次阅读  |  详细内容 »

何为shell

发布于:1年以前  |  1次阅读  |  详细内容 »

Shell语法快速入门

一、基本语法 1.1、shell文件开头 shell文件必须以下面的行开始(必须方在文件的第一行): #!/bin/sh 符号#!用来告诉系统它后面的参数是用来执行该文件的程序。在这个例...

发布于:1年以前  |  1735次阅读  |  详细内容 »

最多阅读

如何查看docker镜像里的文件 1年以前  |  1992次阅读
Shell语法快速入门 1年以前  |  1735次阅读
Shell命令在后台运行程序 1年以前  |  1673次阅读
Shell脚本编程30分钟入门 1年以前  |  599次阅读
shell十三问之12:你要if还是case呢? 1年以前  |  509次阅读
Bash脚本15分钟进阶教程 1年以前  |  500次阅读
shell十三问之11:>与< 差在哪? 1年以前  |  469次阅读
shell十三问之10:&& 与 || 差在哪? 1年以前  |  469次阅读
shell十三问之9:$@与$*差在哪? 1年以前  |  305次阅读
shell十三问之7:()与{}差在哪? 1年以前  |  288次阅读
shell十三问之6:exec跟source差在哪? 1年以前  |  280次阅读