|
|
51CTO旗下网站
|
|
移动端

3.3.1 定义本地变量

《跟老男孩学Linux运维:Shell编程实战》本书是一本较完整的Shell编程实战型图书,并非大而全,但处处可以体现实战二字,大多内容取于企业实战,并结合老男孩十几年的运维工作和教学工作进行了梳理。本节为大家介绍定义本地变量。

作者:老男孩来源:机械工业出版社|2017-04-21 10:44

【51CTO技术沙龙】10月27日,让我们共同探索AI场景化应用实现之道

3.3 普通变量

3.3.1 定义本地变量

本地变量在用户当前Shell生存期的脚本中使用。例如,本地变量oldboy的取值为bingbing,这个值只在用户当前Shell生存期中有意义。如果在Shell中启动另一个进程或退出,那么变量oldboy的值将会无效。

1.普通变量定义

为普通变量的定义赋值,一般有以下3种写法:

变量名=value #<==赋值时不加引号

变量名='value' #<==赋值时加单引号

变量名="value" #<==赋值时加双引号

2.在Shell中定义变量名及为变量内容赋值的要求

变量名一般是由字母、数字、下划线组成的,可以以字母或下划线开头,例如:oldboy、oldboy123、oldboy_training。

变量的内容可以用单引号或双引号引起来,也可不加引号,但是这三者的含义是不同的,具体参见后文说明。

3.普通变量的定义及输出的示例

范例3-4:采用不同的方式对普通变量进行定义,并一一打印输出。

  1. a=192.168.1.2  
  2. b='192.168.1.2' 
  3. c="192.168.1.2" 
  4. echo "a=$a"  
  5. echo "b=$b"  
  6. echo "c=${c}" 

提示:

1)$变量名表示输出变量,可以用$c和${c}两种用法。

2)请在命令行实践以上内容,然后看一看返回的结果有何不同。

思考:在命令行Shell下输入以上内容后会输出什么结果呢?请在看答案之前,先想一想上面a、b、c变量值的输出各是什么,最好自己实践一下。

答案:

  1. a=192.168.1.2  
  2. b=192.168.1.2  
  3. c=192.168.1.2 

可见,将连续的普通字符串的内容赋值给变量,不管用不用引号,或者不管用什么引号,它的内容是什么,打印变量时就会输出什么。

范例3-5:接着上述范例的结果,再在Linux命令行下继续输入如下内容,想一想a、b、c的输出又各是什么结果?

  1. a=192.168.1.2-$a  
  2. b='192.168.1.2-$a' 
  3. c="192.168.1.2-$a" 
  4. echo "a=$a"  
  5. echo "b=$b"  
  6. echo "c=${c}" 

提示: 建议先思考结果是什么,然后再在命令行实践以上内容,看看和思考的结果有何不同。

参考答案:

  1. a=192.168.1.2-192.168.1.2  
  2. b=192.168.1.2-$a  
  3. c=192.168.1.2-192.168.1.2-192.168.1.2 

4.变量定义的基本技巧总结

这里以范例3-5为例:

  1. a=192.168.1.2-$a 

第一种定义a变量的方式是不加任何引号直接定义变量的内容,当内容为简单连续的数字、字符串、路径名时,可以这样用,例如:a=1,b=oldboy等。不加引号时,值里有变量的会被解析后再输出,上述变量定义中因为$a的值被解析为192.168.1.2(范例3-3执行的影响),因此新的a值就是192.168.1.2-192.168.1.2。

  1. b='192.168.1.2-$a' 

第二种定义b变量的方式是通过单引号定义。这种定义方式的特点是:输出变量内容时单引号里是什么就输出什么,即使内容中有变量和命令(命令需要反引起来)也会把它们原样输出。这种方式比较适合于定义显示纯字符串的情况,即不希望解析变量、命令等的场景,因此,对于这里的b的值,定义时看到的是什么就输出什么,即192.168.1.2-$a。

  1. c="192.168.1.2-$a" 

第三种定义c变量的方式是通过双引号定义变量。这种定义方式的特点是:输出变量内容时引号里的变量及命令会经过解析后再输出内容,而不是把双引号中的变量名及命令(命令需要反引起来)原样输出。这种方式比较适合于字符串中附带有变量及命令且想将其解析后再输出的变量定义。

老男孩经验:

数字内容的变量定义可以不加引号,其他没有特别要求的字符串等定义最好都加上双引号,如果真的需要原样输出就加单引号,定义变量加双引号是最常见的使用场景。

5.把一个命令的结果作为变量的内容赋值的方法

对需要获取命令结果的变量内容赋值的常见方法有两种:

变量名=`ls` #<==把命令用反引号引起来,不推荐使用这种方法,因为容易和单引号混淆

变量名=$(ls) #<==把命令用$()括起来,推荐使用这种方法

范例3-6:用两种方法把命令的结果赋值给变量。

  1. [oldboy@oldboy ~]$ ls  
  2. test.sh  
  3. [oldboy@oldboy ~]$ CMD=`ls` #<==其中``为键盘上Tab键上面的那个键输出的字符  
  4. [oldboy@oldboy ~]$ echo $CMD  
  5. test.sh  
  6. [oldboy@oldboy ~]$ CMD1=$(pwd)  
  7. [oldboy@oldboy ~]$ echo $CMD1  
  8. /home/oldboy            #<==打印当前用户所在的目录 

提示: 生产场景中把命令的结果作为变量的内容进行赋值的方法在脚本开发时很常见。

范例3-7:按天打包网站的站点目录程序,生成不同的文件名(此为企业实战案例)。

  1. [root@oldboy scripts]# CMD=$(date +%F)  #<==将当前日期(格式为2016-09-10)赋值  
  2.                            ??给CMD变量  
  3. [root@oldboy scripts]# echo $CMD            #<==输出变量的值  
  4. 2016-09-10  
  5. [root@oldboy scripts]# echo $(date +%F).tar.gz  #<==直接输出时间命令的结果  
  6. 2016-09-10.tar.gz  
  7. [root@oldboy scripts]# echo `date +%F`.tar.gz  
  8. 2016-09-10.tar.gz  
  9. [root@oldboy scripts]# tar zcf etc_$(date +%F).tar.gz /etc  
  10.                             #<==将时间作为压缩包名打包  
  11. tar: 从成员名中删除开头的“/”  
  12. tar: 从硬连接目标中删除开头的“/”  
  13. [root@oldboy scripts]# ls -l etc_2016-09-10.tar.gz  #<==打包结果,包名中包含  
  14.                                                               ?有当前日期  
  15. -rw-r--r-- 1 root root 9700163 9月  10 18:39 etc_2016-09-10.tar.gz  
  16. [root@oldboy scripts]# H=$(uname -n)    #<==获取主机名并赋值给H变量  
  17. [root@oldboy scripts]# echo $H  
  18. oldboy  
  19. [root@oldboy scripts]# tar zcf $H.tar.gz /etc/services  ?#<==将主机名作为压缩包名  
  20.                                                           ?打包文件  
  21. tar: 从成员名中删除开头的“/”  
  22. [root@oldboy scripts]# ls -l oldboy.tar.gz  #<==打包结果,包名中包含有主机名  
  23. -rw-r--r-- 1 root root 127303 9月  10 18:40 oldboy.tar.gz 

局部(普通)变量定义及赋值的经验小结

常规普通变量定义:

若变量内容为连续的数字或字符串,赋值时,变量内容两边可以不加引号,例如a=123。

变量的内容很多时,如果有空格且希望解析内容中的变量,就加双引号,例如a="/etc/rc.local $USER" ,此时输出变量会对内容中的$USER进行解析然后再输出。

希望原样输出变量中的内容时就用单引号引起内容进行赋值,例如:a='$USER'。

希望变量的内容是命令的解析结果的定义及赋值如下:

要使用反引号将赋值的命令括起来,例如:a=`ls`;或者用$()括起来,例如:a=$(ls)。

变量的输出方法如下:

使用“$变量名”即可输出变量的内容,常用“echo $变量名”的方式,也可用printf代替echo输出更复杂的格式内容。

变量定义的技巧及注意事项:

注意命令变量内容前后的字符``(此字符为键盘Tab键上面的那个反引号,不是单引号),例如:“CMD=`ls`”。

在变量名前加$可以取得该变量的值,使用echo或printf命令可以显示变量的值,$A和${A}的写法不同,但效果是一样的。

用echo等命令输出变量的时候,也可用单引号、双引号、反引号,例如:echo $A、echo "$A"、echo '$A',它们的用法和前面变量内容定义的总结是一致的。

$dbname_tname,当变量后面连接有其他字符的时候,必须给变量加上大括号{},例如:$dbname_tname就要改成${dbname}_tname。

有关上述变量问题输出的小故事

故事1:老男孩正在给面授班讲课,发了一段内容,结果引起群里网络班学员的强烈反应,下面是对话内容。

老男孩(31333741)  12:42:54

金庸新著

XXX-学员?12:43:39

老师,金庸又写啥小说了? #<==看到了吧,这引起了误解

老男孩(31333741)?12:42:54

这是一本小说,作者为金庸新,而非金庸,但是给读者造成的感觉是{金庸}新著。

$dbname_tname变量就类似于这个金庸新著,会引起歧义,因此要改成${dbname}_tname,Shell就会认为只有dbname是变量了。

老男孩(31333741)?12:44:45

如果真的是金庸新著,就要像这样用大括号分隔开,${金庸}新著。

故事2:老男孩运维班20期的李同学在他媳妇看电视剧时发现了这个金庸新著,于是他将电视剧停下来,还截图发给了我。

可见形象的比喻学习对学生的影响非常深远!养成将所有字符串变量用大括号括起来的习惯,在编程时将会减少很多问题。不过老男孩也并不是一直都这么做,因为多输入内容会造成效率不高,但是金庸新著的问题确实要多注意。
喜欢的朋友可以添加我们的微信账号:

51CTO读书频道二维码


51CTO读书频道活动讨论群:342347198

【责任编辑:book TEL:(010)68476606】

回书目   上一节   下一节
点赞 0
分享:
大家都在看
猜你喜欢

读 书 +更多

精通SOA:基于服务总线的Struts+EJB+Web Service

Java的出现,实现了跨操作系统平台的程序开发,以Java为基础的J2EE技术已经成为因特网服务技术的主流。然而,以J2EE为基础的SOA架构技术必...

订阅51CTO邮刊

点击这里查看样刊

订阅51CTO邮刊