Linux【3】--BASH介绍4--变量的取用与设定(echo,unset)

可以利用 echo 这个指令来取用变量,但是,变量在被取用时,前面必须要加上钱字号 $ 才行,举例来说,要知道 PATH 的内容,该如何是好?

一、变量的取用: echo

[root@www ~]# echo $variable
[root@www ~]# echo $PATH
/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
[root@www ~]# echo ${PATH}

变量的取用就如同上面的范例,利用 echo 就能够读出,只是需要在变量名称前面加上 $ , 或者是以 ${变量} 的方式来取用都可以!当然啦,那个 echo 的功能可是很多的, 我们这里单纯是拿 echo 来读出变量的内容而已,更多的 echo 使用,请自行给他 man echo 吧!

例题:

请在屏幕上面显示出您的环境变量 HOME 与 MAIL:

答:

echo $HOME 或者是 echo ${HOME}
echo $MAIL 或者是 echo ${MAIL}

现在我们知道了变量与变量内容之间的相关性了,好了,那么我要如何『设定』或者是『修改』 某个变量的内容啊?很简单啦!用『等号(=)』连接变量与他的内容就好啦!举例来说: 我要将 myname 这个变量名称的内容设定为VBird ,那么:

[root@www ~]# echo $myname
       <==这里并没有任何数据~因为这个变量尚未被设定!是空的!

[root@www ~]# myname=VBird
[root@www ~]# echo $myname
VBird  <==出现了!因为这个变量已经被设定了!

瞧!如此一来,这个变量名称 myname 的内容就带有 VBird 这个数据啰~ 而由上面的例子当中,我们也可以知道: 在 bash 当中,当一个变量名称尚未被设定时,预设的内容是『空』的。 另外,变量在设定时,还是需要符合某些规定的,否则会设定失败喔! 这些规则如下所示啊!

二、变量的设定规则

变量与变量内容以一个等号 = 来连结,如下所示:

myname=VBird

等号两边不能直接接空格符,如下所示为错误:

myname = VBird 或 myname=VBird Tsai

变量名称只能是英文字母与数字,但是开头字符不能是数字,如下为错误:

2myname=VBird

变量内容若有空格符可使用双引号 " 或单引号 ' 将变量内容结合起来,但

双引号内的特殊字符如 $ 等,可以保有原本的特性,如下所示:

var="lang is $LANG" 则 echo $var 可得 lang is en_US

单引号内的特殊字符则仅为一般字符 (纯文本),如下所示:

var='lang is $LANG' 则 echo $var 可得lang is $LANG

可用跳脱字符 \ 将特殊符号(如 [Enter], $, , 空格符, ‘等)变成一般字符;

在一串指令中,还需要藉由其他的指令提供的信息,可以使用反单引号

`指令` 或 $(指令)。

特别注意,那个 ` 是键盘上方的数字键 1 左边那个按键,而不是单引号! 例如想要取得核心版本的设定:

version=$(uname -r) 再 echo $version 可得 2.6.18-128.el5

若该变量为扩增变量内容时,则可用 “$变量名称” 或 ${变量} 累加内容,如下所示:

PATH="$PATH":/home/bin

三、变量变成环境变量 export

若该变量需要在其他子程序执行,则需要以 export 来使变量变成环境变量:

export PATH

通常大写字符为系统默认变量,自行设定变量可以使用小写字符,方便判断 (纯粹依照使用者兴趣与嗜好) ;

四、取消变量 unset

unset [-fv][变量或函数名称]

参数:

-f  仅删除函数。
-v  仅删除变量。

取消变量的方法为使用 unset :unset 变量名称 例如取消 myname 的设定:

unset myname

底下让鸟哥举几个例子来让你试看看,就知道怎么设定好你的变量啰!

五、更多例子

范例一:设定一变量 name ,且内容为 VBird

[root@www ~]# 12name=VBird

-bash: 12name=VBird: command not found  <==屏幕会显示错误!因为不能以数字开头!

[root@www ~]# name = VBird            <==还是错误!因为有空白!
[root@www ~]# name=VBird              <==OK 的啦!

范例二:承上题,若变量内容为VBird’s name 呢,就是变量内容含有特殊符号时:

[root@www ~]# name=VBird's name 

#单引号与双引号必须要成对,在上面的设定中仅有一个单引号,因此当你按下 enter 后,

#你还可以继续输入变量内容。这与我们所需要的功能不同,失败啦!

#记得,失败后要复原请按下[ctrl]-c 结束!

[root@www ~]# name="VBird's name"    <==OK 的啦!

#指令是由左边向右找→,先遇到的引号先有用,因此如上所示,单引号会失效!

[root@www ~]# name='VBird's name'    <==失败的啦!

#因为前两个单引号已成对,后面就多了一个不成对的单引号了!因此也就失败了!

[root@www ~]# name=VBird\'s\ name     <==OK 的啦!

#利用反斜杠 () 跳脱特殊字符,例如单引号与空格键,这也是 OK 的啦!

范例三:我要在 PATH 这个变量当中『累加』:/home/dmtsai/bin 这个目录

[root@www ~]# PATH=$PATH:/home/dmtsai/bin
[root@www ~]# PATH="$PATH":/home/dmtsai/bin
[root@www ~]# PATH=${PATH}:/home/dmtsai/bin

#上面这三种格式在 PATH 里头的设定都是 OK 的!但是底下的例子就不见得啰!

范例四:承范例三,我要将 name 的内容多出"yes" 呢?

[root@www ~]# name=$nameyes 

#知道了吧?如果没有双引号,那么变量成了啥?name 的内容是 $nameyes 这个变量!

#呵呵!我们可没有设定过nameyes 这个变量吶!所以,应该是底下这样才对!

[root@www ~]# name="$name"yes
[root@www ~]# name=${name}yes  <==以此例较佳!

范例五:如何让我刚刚设定的name=VBird 可以用在下个 shell 的程序?

[root@www ~]# name=VBird

[root@www ~]# bash        <==进入到所谓的子程序

[root@www ~]# echo $name  <==子程序:再次的 echo 一下;
       <==嘿嘿!并没有刚刚设定的内容喔!

[root@www ~]# exit        <==子程序:离开这个子程序

[root@www ~]# export name

[root@www ~]# bash        <==进入到所谓的子程序

[root@www ~]# echo $name  <==子程序:在此执行!
VBird  <==看吧!出现设定值了!

[root@www ~]# exit        <==子程序:离开这个子程序

什么是『子程序』呢?就是说,在我目前这个shell 的情况下,去启用另一个新的 shell ,新的那个 shell 就是子程序啦!在一般的状态下,父程序的自定义变量是无法在子程序内使用的。但是透过 export 将变量变成环境变量后,就能够在子程序底下应用了!很不赖吧!至于程序的相关概念, 我们会在第十七章程序管理当中提到的喔!

范例六:如何进入到您目前核心的模块目录?

[root@www ~]# cd /lib/modules/`uname -r`/kernel
[root@www ~]# cd /lib/modules/$(uname -r)/kernel

每个 Linux 都能够拥有多个核心版本,且几乎 distribution 的核心版本都不相同。以 CentOS 5.3 (未更新前) 为例,他的预设核心版本是 2.6.18-128.el5 ,所以核心模块目录在 /lib/modules/2.6.18-128.el5/kernel/ 内。 也由于每个 distributions 的这个值都不相同,但是我们却可以利用 uname -r 这个指令先取得版本信息。所以啰,就可以透过上面指令当中的内含指令

`uname -r` 

先取得版本输出到 cd … 那个指令当中,就能够顺利的进入目前核心的驱动程序所放置的目录啰!很方便吧!

其实上面的指令可以说是作了两次动作,亦即是:

先进行反单引号内的动作『uname -r』并得到核心版本为2.6.18-128.el5

将上述的结果带入原指令,故得指令为:『cd /lib/modules/2.6.18-128.el5/kernel/』

范例七:取消刚刚设定的 name 这个变量内容

[root@www ~]# unset name

根据上面的案例你可以试试看!就可以了解变量的设定啰!这个是很重要的呦!请勤加练习! 其中,较为重要的一些特殊符号的使用啰!例如单引号、双引号、跳脱字符、钱字号、反单引号等等,底下的例题想一想吧!

六、讨论

6.1 在变量的设定当中,单引号与双引号的用途有何不同?

单引号与双引号的最大不同在于双引号仍然可以保有变量的内容,但单引号内仅能是一般字符 ,而不会有特殊符号。我们以底下的例子做说明:假设您定义了一个变量, name=VBird ,现在想以 name 这个变量的内容定义出 myname 显示 VBird its me 这个内容,要如何订定呢?

[root@www ~]# name=VBird

[root@www ~]# echo $name

VBird

[root@www ~]# myname="$name its me"

[root@www ~]# echo $myname

VBird its me

[root@www ~]# myname='$name its me'

[root@www ~]# echo $myname

$name its me

发现了吗?没错!使用了单引号的时候,那么$name 将失去原有的变量内容,仅为一般字符的显示型态而已!这里必需要特别小心在意!

6.2 在指令下达的过程中,反单引号( ` )这个符号代表的意义为何?

在一串指令中,在 ` 之内的指令将会被先执行,而其执行出来的结果将做为外部的输入信息!例如 uname -r 会显示出目前的核心版本,而我们的核心版本在 /lib/modules 里面,因此,你可以先执行 uname -r 找出核心版本,然后再以『 cd 目录』到该目录下,当然也可以执行如同上面范例六的执行内容啰。

另外再举个例子,我们也知道, locate 指令可以列出所有的相关档案档名,但是,如果我想要知道各个档案的权限呢?举例来说,我想要知道每个 crontab 相关档名的权限:

[root@www ~]# ls -l `locate crontab`

如此一来,先以 locate 将文件名数据都列出来,再以ls 指令来处理的意思啦!瞭了吗? ^_^

6.3 若你有一个常去的工作目录名称为:『/cluster/server/work/taiwan_2005/003/』,如何进行该目录的简化?

在一般的情况下,如果你想要进入上述的目录得要『cd /cluster/server/work/taiwan_2005/003/』, 以鸟哥自己的案例来说,鸟哥跑数值模式常常会设定很长的目录名称(避免忘记),但如此一来变换目录就很麻烦。 此时,鸟哥习惯利用底下的方式来降低指令下达错误的问题:

[root@www ~]# work="/cluster/server/work/taiwan_2005/003/"

[root@www ~]# cd $work

未来我想要使用其他目录作为我的模式工作目录时,只要变更 work 这个变量即可!而这个变量又可以在 bash 的配置文件中直接指定,那我每次登入只要执行『 cd $work 』就能够去到数值模式仿真的工作目录了!是否很方便呢? ^_^

6.4 Tips:

老实说,使用『version=$(uname -r) 』来取代

『 version=`uname -r` 』

比较好,因为反单引号大家老是容易打错或看错! 所以现在鸟哥都习惯使用 $( 指令 ) 来介绍这个功能!

更多说明:

man echo

参考资料

鸟哥私房菜 http://linux.vbird.org/linux_basic/0320bash.php#variable_echo

药企,独角兽,苏州。团队长期招人,感兴趣的都可以发邮件聊聊:tiehan@sina.cn
个人公众号,比较懒,很少更新,可以在上面提问题,如果回复不及时,可发邮件给我: tiehan@sina.cn