ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
##shell十三问之5:问var=value 在export前后的差在哪? ---------------------------------------------------- 这次让我们暂时丢开`command line`, 先了解一下bash变量(variable)吧... 所谓的变量,就是利用一个固定的"名称"(name), 来存取一段可以变化的"值"(value)。 ###1. 变量设定(set) 在bash中, 你可以用"="来设定或者重新定义变量的内容: ```shell name=value ``` 在设定变量的时候,得遵守如下规则: - 等号左右两边不能使用分隔符号(IFS),也应避免使用shell的保留元字符(meta charactor); - 变量的名称(name)不能使用$符号; - 变量的名称(name)的首字符不能是数字(number)。 - 变量的名称(name)的长度不可超过256个字符。 - 变量的名称(name)及变量的值的大小写是有区别的、敏感的(case sensitive,) 如下是一些变量设定时常见的错误: ```shell A= B #=号前后不能有IFS 1A=B #变量名称不能以数字开头 $A=B #变量的名称里有$ a=B #这跟a=b是不同的,(这不是错误,提醒windows用户) ``` 如下则是可以接受的设定: ```shell A=" B" #IFS被关闭,参考前面的quoting章节 A1=B #并非以数字开头 A=$B #$可用在变量的值内 This_Is_A_Long_Name=b #可用_连接较长的名称或值,且有大小区别; ``` ###2. 变量替换(substitution) shell 之所以强大,其中的一个因素是它可以在命令行中对变量作 替换(substitution)处理。 在命令行中使用者可以使用$符号加上变量名称(除了用=定义变量名称之外), 将变量值给替换出来,然后再重新组建命令行。 比方: ```shell $ A=ls $ B=la $ C=/tmp $ $A -$B $C ``` 以上命令行的第一个`$`是`shell prompt`, 并不在命令行之内。 必须强调的是,我们所提的变量替换,只发生在`command line`上面。 (是的,请让我们再次回到命令行吧!) 仔细分析,最后那行 `command line`,不难发现在被执行前(在输入`CR`字符之前), `$`符号对每一个变量作替换处理(将变量的值替换出来再重组命令行), 最后会得出如下命令行: ```shell ls -la /tmp ``` 还记得第二章,我请大家"务必理解"的那两句吗? 若你忘了,我这里重贴一遍: > **Note:** > 若从技术的细节来看,`shell`会依据`IFS`(Internal Field Seperator) > 将`command line`所输入的文字拆解为"字段"(word/field)。 > 然后再针对特殊字符(meta)先作处理,最后重组整行`command line`。 这里的`$`就是`command line`中最经典的meta之一了, 就是作变量替换的。在日常的shell操作中, 我们常会使用`echo`命令来查看特定的变量的值, 例如: ```shell $ echo $A -$B $C ``` 我们已学过,`echo`命令只单纯将其argument送至"标准输出"(stdout, 通常是我们的屏幕)。 所以上面的命令会在屏幕上得到如下结果: ```shell ls -al /tmp ``` 这是由于`echo`命令在执行时,会先将`$A` (ls)、`$B` (la)跟`$C` (/tmp)给替换出来; 利用shell对变量的替换处理能力,我们在设定变量时就更为灵活了: ```shell A=B B=$A ``` 这样,B的变量值就可继承A变量"当时"的变量值了。 不过,不要以"数学逻辑"来套用变量的设定,比方说: ```shell A=B B=C ``` 这样,并不会让A的变量值变成C。再如: ```shell A=B B=$A A=C ``` 同样也不会让B的值变成C。 上面是单纯定义了两个不同名称的变量: A 与 B, 它们的取值分别是C与B。 若变量被重复定义的话,则原有值为新值所取代。(这不正是"可变的量"吗?^_^) 当我们在设定变量的时候,请记住这点:**用一个名称存储一个数值**, 仅此而已。 此外, 我们也可以利用命令行的变量替换能力来"扩充"(append)变量的值: ```shell A=B:C:D A=$A:E ``` 这样, 第一行我们设定A的值为"B:C:D", 然后,第二行再将值扩充为"B:C:D:E"。 上面的扩充的范例,我们使用分隔符号(:)来达到扩充的目的, 要是没有分隔符的话,如下是有问题的: ```shell A=BCD B=$AE ``` 因为第二次是将A的值继承$AE的替换结果,而非$A再加E。 要解决此问题,我们可用更严谨的替换处理: ```shell A=BCD A=${A}E ``` 上例中,我们使用{}将变量名称范围给明确定义出来, 如此一来, 我们就可以将A的变量值从BCD给扩充为BCDE。 > **Tips:** > 关于${name}事实上还可以做到更多的变量处理能力, > 这些均属于比较进阶阶段的变量处理,现阶段暂不介绍了, > 请大家自行参考资料。 ###3. export 变量 严格来说,我们在当前shell中所定义的变量,均属于 "本地变量"(local variable), 只有经过`export`命令的 "输出"处理,才能成为"环境变量"(environment variable): ```shell $ A=B $ export A ``` 或者 ```shell $ export A=B ``` 经过`export`输出处理之后,变量A就能成为一个环境变量 供其后的命令使用。在使用`export`的时候,请别忘记 shell在命令行对变量的"替换"(substitution)处理。 比方说: ```shell $ A=B $ B=C $ export $A ``` 上面的命令并未将A输出为"环境变量",而是将B导出 这是因为在这个命令行中,$A会首先被替换为B,然后在"塞回" 作`export`的参数。 要理解这个`export`,事实上需要从process(进程)的角度来理解才能透彻。 我们将于下一章为大家说明process(进程)的概念,敬请留意。 ####4. 取消变量(unset) 要取消一个变量,在bash中可使用`unset`命令来处理: ```shell unset A ``` 与`export`一样,`unset`命令行,也同样会作 变量替换(这其实是shell的功能之一), 因此: ```shell $ A=B $ B=C $ unset $A ``` 事实上,所取消的是变量B而不是A。 此外,变量一旦经过unset取消之后, 其结果是将整个变量拿掉,而不是取消变量的值。 如下两行其实是很不一样的: ```shell $ A= $ unset A ``` 第一行只是将变量A设定为"空值"(null value), 但第二行则是让变量A不存在。 虽然用眼睛来看, 这两种变量的状态在如下的命令结果中都是一样的: ```shell $ A= $ echo $A $ unset A $ echo $A ``` 请学员务必能识别null value 与 unset的本质区别, 这在一些进阶的变量处理上是很严格的。 比方说: ```shell $ 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} 这个进阶处理 - 对本篇说明还没有来得及消化吸收 - 我讲得不好 不知,您选哪个呢?...... ^_^.