概要:
shell中,变量有环境变量和自定义变量之分,环境 变量相当于全局变量,自定义变量相当于局部变量,因此父程序的环境变量变量会被子程序所引用,而自定义变量则不可以。其中的原因在于子程序仅会继承父程序的环境变量, 子程序不会继承父程序的自定义变量。
- 为什么环境变量的数据可以被子程序所引用呢?这是因为内存配置的关系!理论上是这样的:
- 当启动一个 shell,操作系统会分配一记忆区块给 shell 使用,此内存内之变量可让子程序取用
- 若在父程序利用 export 功能,可以让自定义变量的内容写到上述的记忆区块当中(环境变量);
- 当加载另一个 shell 时 (亦即启动子程序,而离开原本的父程序了),子 shell 可以将父 shell 的环境变量所在的记忆区块导入自己的环境变量区块当中。
- 本文目录索引:
- 1、
- 2、
- 3、
- 4、
- 5、
- ( )
变量的显示
echo --显示变量内容 |
- 格式:echo $variable
- echo ${variable}
- echo $PATH
- /usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
- [root@www ~]# echo ${PATH}
- /usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
unset --取消变量 |
- 格式:unset 变量名称
- 取消 myname 的配置:
- [root@www ~]#unset myname
env --观察环境变量 |
- 范例一:列出目前的 shell 环境下的所有环境变量与其内容。
- [root@www ~]# env
- HOSTNAME=www.vbird.tsai <== 这部主机的主机名
- TERM=xterm <== 这个终端机使用的环境是什么类型
- SHELL=/bin/bash <== 目前这个环境下,使用的 Shell 是哪一个程序?
- HISTSIZE=1000 <== 『记录命令的笔数』在 CentOS 默认可记录 1000 笔
- USER=root <== 使用者的名称啊!
- LS_COLORS=no=00:fi=00:di=00;34:ln=00;36:pi=40;33:so=00;35:bd=40;33;01:cd=40;33;01:
- or=01;05;37;41:mi=01;05;37;41:ex=00;32:*.cmd=00;32:*.exe=00;32:*.com=00;32:*.btm=0
- 0;32:*.bat=00;32:*.sh=00;32:*.csh=00;32:*.tar=00;31:*.tgz=00;31:*.arj=00;31:*.taz=
- 00;31:*.lzh=00;31:*.zip=00;31:*.z=00;31:*.Z=00;31:*.gz=00;31:*.bz2=00;31:*.bz=00;3
- 1:*.tz=00;31:*.rpm=00;31:*.cpio=00;31:*.jpg=00;35:*.gif=00;35:*.bmp=00;35:*.xbm=00
- ;35:*.xpm=00;35:*.png=00;35:*.tif=00;35: <== 一些颜色显示
- MAIL=/var/spool/mail/root <== 这个用户所取用的 mailbox 位置
- PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/X11R6/bin:/usr/local/bin:/usr/local/sbin:
- /root/bin <== 不再多讲啊!是运行文件命令搜寻路径
- INPUTRC=/etc/inputrc <== 与键盘按键功能有关。可以配置特殊按键!
- PWD=/root <== 目前用户所在的工作目录 (利用 pwd 取出!)
- LANG=en_US <== 这个与语系有关,底下会再介绍!
- HOME=/root <== 这个用户的家目录啊!
- _=/bin/env <== 上一次使用的命令的最后一个参数(或命令本身)
部分环境变量的介绍如下:
- HOME
- 代表用户的家目录。还记得我们可以使用 cd ~ 去到自己的家目录吗?或者利用 cd 就可以直接回到用户家目录了。那就是取用这个变量啦~ 有很多程序都可能会取用到这个变量的值!
- SHELL
- 告知我们,目前这个环境使用的 SHELL 是哪支程序? Linux 默认使用 /bin/bash 的啦!
- HISTSIZE
- 这个与『历史命令』有关,亦即是, 我们曾经下达过的命令可以被系统记录下来,而记录的『笔数』则是由这个值来配置的。
- 当我们使用 mail 这个命令在收信时,系统会去读取的邮件信箱文件 (mailbox)。
- PATH
- 就是运行文件搜寻的路径啦~目录与目录中间以冒号(:)分隔, 由于文件的搜寻是依序由 PATH 的变量内的目录来查询,所以,目录的顺序也是重要的喔。
- LANG
- 这个重要!就是语系数据啰~很多信息都会用到他, 举例来说,当我们在启动某些 perl 的程序语言文件时,他会主动的去分析语系数据文件, 如果发现有他无法解析的编码语系,可能会产生错误喔!一般来说,我们中文编码通常是 zh_TW.Big5 或者是 zh_TW.UTF-8,这两个编码偏偏不容易被解译出来,所以,有的时候,可能需要修订一下语系数据。 这部分我们会在下个小节做介绍的!
- RANDOM
- 这个玩意儿就是『随机随机数』的变量啦!目前大多数的 distributions 都会有随机数生成器,那就是 /dev/random 这个文件。 我们可以透过这个随机数文件相关的变量 ($RANDOM) 来随机取得随机数值喔。在 BASH 的环境下,这个 RANDOM 变量的内容,介于 0~32767 之间,所以,你只要 echo $RANDOM 时,系统就会主动的随机取出一个介于 0~32767 的数值。万一我想要使用 0~9 之间的数值呢?呵呵~利用 declare 宣告数值类型, 然后这样做就可以了:
- [root@www ~]# declare -i number=$RANDOM*10/32768
- [root@www ~]# echo $number
- 8 <== 此时会随机取出 0~9 之间的数值喔!
set --观察环境变量与自定义变量 |
- 一般来说,不论是否为环境变量,只要跟我们目前这个 shell 的操作接口有关的变量, 通常都会被配置为大写字符,也就是说,『基本上,在 Linux 默认的情况中,使用{大写的字母}来配置的变量一般为系统内定需要的变量』。 OK!OK!那么上头那些变量当中,有哪些是比较重要的?大概有这几个吧!
- PS1:(提示字符的配置)
- 这是 PS1 (数字的 1 不是英文字母),这个东西就是我们的『命令提示字符』喔! 当我们每次按下 [Enter] 按键去运行某个命令后,最后要再次出现提示字符时, 就会主动去读取这个变量值了。上头 PS1 内显示的是一些特殊符号,这些特殊符号可以显示不同的信息, 每个 distributions 的 bash 默认的 PS1 变量内容可能有些许的差异,不要紧,『习惯你自己的习惯』就好了。 你可以用 man bash (注3)去查询一下 PS1 的相关说明,以理解底下的一些符号意义。
- \d :可显示出『星期 月 日』的日期格式,如:"Mon Feb 2"
- \H :完整的主机名。举例来说,鸟哥的练习机为『www.vbird.tsai』
- \h :仅取主机名在第一个小数点之前的名字,如鸟哥主机则为『www』后面省略
- \t :显示时间,为 24 小时格式的『HH:MM:SS』
- \T :显示时间,为 12 小时格式的『HH:MM:SS』
- \A :显示时间,为 24 小时格式的『HH:MM』
- \@ :显示时间,为 12 小时格式的『am/pm』样式
- \u :目前使用者的账号名称,如『root』;
- \v :BASH 的版本信息,如鸟哥的测试主板本为 3.2.25(1),仅取『3.2』显示
- \w :完整的工作目录名称,由根目录写起的目录名称。但家目录会以 ~ 取代;
- \W :利用 basename 函数取得工作目录名称,所以仅会列出最后一个目录名。
- \# :下达的第几个命令。
- \$ :提示字符,如果是 root 时,提示字符为 # ,否则就是 $ 啰~
- 好了,让我们来看看 CentOS 默认的 PS1 内容吧:『[\u@\h \W]\$ 』,现在你知道那些反斜杠后的数据意义了吧? 要注意喔!那个反斜杠后的数据为 PS1 的特殊功能,与 bash 的变量配置没关系啦!不要搞混了喔! 那你现在知道为何你的命令提示字符是:『 [root@www ~]# 』了吧? 好了,那么假设我想要有类似底下的提示字符:
- [root@www /home/dmtsai 16:50 #12]#
- 那个 # 代表第 12 次下达的命令。那么应该如何配置 PS1 呢?可以这样啊:
- [root@www ~ ]# cd /home
- [root@www home]# PS1='[\u@\h \w \A #\#]\$ '
- [root@www /home 17:02 #85]#
- # 看到了吗?提示字符变了!变的很有趣吧!其中,那个 #85 比较有趣,
- # 如果您再随便输入几次 ls 后,该数字就会添加喔!为啥?上面有说明滴!
- $:(关于本 shell 的 PID)
- 钱字号本身也是个变量喔!这个咚咚代表的是『目前这个 Shell 的线程代号』,亦即是所谓的 PID (Process ID)。 更多的程序观念,我们会在第四篇的时候提及。想要知道我们的 shell 的 PID ,就可以用:『 echo $$ 』即可!出现的数字就是你的 PID 号码。
- ?:(关于上个运行命令的回传值)
- 什么?问号也是一个特殊的变量?没错!在 bash 里面这个变量可重要的很! 这个变量是:『上一个运行的命令所回传的值』, 上面这句话的重点是『上一个命令』与『回传值』两个地方。当我们运行某些命令时, 这些命令都会回传一个运行后的代码。一般来说,如果成功的运行该命令, 则会回传一个 0 值,如果运行过程发生错误,就会回传『错误代码』才对!一般就是以非为 0 的数值来取代。 我们以底下的例子来看看:
- [root@www ~]# echo $SHELL
- /bin/bash <==可顺利显示!没有错误!
- [root@www ~]# echo $?
- 0 <==因为没问题,所以回传值为 0
- [root@www ~]# 12name=VBird
- -bash: 12name=VBird: command not found <==发生错误了!bash回报有问题
- [root@www ~]# echo $?
- 127 <==因为有问题,回传错误代码(非为0)
- # 错误代码回传值依据软件而有不同,我们可以利用这个代码来搜寻错误的原因喔!
- [root@www ~]# echo $?
- 0
- # 咦!怎么又变成正确了?这是因为 "?" 只与『上一个运行命令』有关,
- # 所以,我们上一个命令是运行『 echo $? 』,当然没有错误,所以是 0 没错!
- OSTYPE, HOSTTYPE, MACHTYPE:(主机硬件与核心的等级)
- 我们在第零章、计算器概论内的 CPU 等级说明中谈过 CPU , 目前个人计算机的 CPU 主要分为 32/64 位,其中 32 位又可分为 i386, i586, i686,而 64 位则称为 x86_64。 由于不同等级的 CPU 命令集不太相同,因此你的软件可能会针对某些 CPU 进行优化,以求取较佳的软件性能。 所以软件就有 i386, i686 及 x86_64 之分。以目前 (2009) 的主流硬件来说,几乎都是 x86_64 的天下! 但是毕竟旧机器还是非常多,以鸟哥的环境来说,我用 P-III 等级的计算机,所以上头就发现我的等级是 i686 啦!
- 要留意的是,较高阶的硬件通常会向下兼容旧有的软件,但较高阶的软件可能无法在旧机器上面安装! 我们在第三章就曾说明过, 这里再强调一次,你可以在 x86_64 的硬件上安装 i386 的 Linux 操作系统,但是你无法在 i686 的硬件上安装 x86_64 的 Linux 操作系统!这点得要牢记在心!
export --自定义变量转成环境变量 |
export可以将自定义变量变成环境变量,让该变量值继续存在于子程序,让该变量内容继续的在子程序中使用。
- 格式:export 变量名称
如果仅下达 export 而没有接变量时,那么此时将会把所有的『环境变量』显示出来!例如:
- [root@www ~]# export
- declare -x HISTSIZE="1000"
- declare -x HOME="/root"
- declare -x HOSTNAME="www.vbird.tsai"
- declare -x INPUTRC="/etc/inputrc"
- declare -x LANG="en_US"
- declare -x LOGNAME="root"
declare / typeset --宣告变量的类型(也可以将环境变量转成自定义变量) |
declare 语法如下:
如果你不小心将变量配置为『只读』,通常得要注销再登陆才能复原该变量的类型了!
在默认的情况底下, bash 对于变量有几个基本的定义:
- 变量类型默认为『字符串』,所以若不指定变量类型,则 1+2 为一个『字符串』而不是『计算式』。 所以上述第一个运行的结果才会出现那个情况的;
- bash 环境中的数值运算,默认最多仅能到达整数形态,所以 1/3 结果是 0;
变量的读取
read --读取来自键盘输入的变量
通配符与特殊符号
变量的配置守则
- 1.变量名称只能是英文字母与数字,但是开头字符不能是数字,如下为错误:
- 『2myname=VBird』
- 2.等号两边不能直接接空格符,如下所示为错误:
- 『myname = VBird』或『myname=VBird Tsai』
- 3.变量内容若有空格符可使用双引号『"』或单引号『'』将变量内容结合起来,但
- 双引号内的特殊字符如 $ 等,可以保有原本的特性,如下所示:
- 『var="lang is $LANG"』则『echo $var』可得『lang is en_US』
- 单引号内的特殊字符则仅为一般字符 (纯文本),如下所示:
- 『var='lang is $LANG'』则『echo $var』可得『lang is $LANG』
- 4.在一串命令中,还需要藉由其他的命令提供的信息,可以使用反单引号『`命令`』或 『$(命令)』。特别注意,那个 ` 是键盘上方的数字键 1 左边那个按键,而不是单引号! 例如想要取得核心版本的配置:
- 『version=$(uname -r)』再『echo $version』可得『2.6.18-128.el5』
- 5.可用跳脱字符『 \ 』将特殊符号(如 [Enter], $, \, 空格符, '等)变成一般字符;
- 6.若该变量为扩增变量内容时,则可用 "$变量名称" 或 ${变量} 累加内容,如下所示:
- 『PATH="$PATH":/home/bin』
- 7.通常大写字符为系统默认变量,自行配置变量可以使用小写字符,方便判断 (纯粹依照使用者兴趣与嗜好) ;
- 8.若该变量需要在其他子程序运行,则需要以 export 来使变量变成环境变量:
- 『export PATH』
举例如下:
根据上面的案例你可以试试看!就可以了解变量的配置啰!这个是很重要的呦!请勤加练习! 其中,较为重要的一些特殊符号的使用啰!例如单引号、双引号、跳脱字符、钱字号、反单引号等等,底下的例题想一想吧!例题:
例题: 在变量的配置当中,单引号与双引号的用途有何不同? 答: 单引号与双引号的最大不同在于 双引号仍然可以保有变量的内容,但单引号内仅能是一般字符 ,而不会有特殊符号。我们以底下的例子做说明:假设您定义了一个变量, 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 将失去原有的变量内容,仅为一般字符的显示型态而已!这里必需要特别小心在意! |
例题: 在命令下达的过程中,反单引号( ` )这个符号代表的意义为何? 答: 在一串命令中,在 ` 之内的命令将会被先运行,而其运行出来的结果将做为外部的输入信息!例如 uname -r 会显示出目前的核心版本,而我们的核心版本在 /lib/modules 里面,因此,你可以先运行 uname -r 找出核心版本,然后再以『 cd 目录』到该目录下,当然也可以运行如同上面范例六的运行内容啰。 另外再举个例子,我们也知道, 命令可以列出所有的相关文件档名,但是,如果我想要知道各个文件的权限呢?举例来说,我想要知道每个 crontab 相关档名的权限: [root@www ~]# ls -l `locate crontab`如此一来,先以 locate 将文件名数据都列出来,再以 ls 命令来处理的意思啦!瞭了吗? ^_^ |
例题: 若你有一个常去的工作目录名称为:『/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 这个变量即可!而这个变量又可以在 中直接指定,那我每次登陆只要运行『 cd $work 』就能够去到数值模式仿真的工作目录了!是否很方便呢? ^_^ |
Tips: 老实说,使用『 version=$(uname -r) 』来取代『 version=`uname -r` 』比较好,因为反单引号大家老是容易打错或看错! 所以现在鸟哥都习惯使用 $( 命令 ) 来介绍这个功能!变量内容的删除、取代与测试、替换 |
变量内容的删除与取代 |
1、删除:
- # :符合取代文字的『最短的』那一个;
- ##:符合取代文字的『最长的』那一个 ;
eg:『从前面开始删除变量内容』
eg:『从后面向前删除变量内容』
由于我是想要由变量内容的后面向前面删除,而我这个变量内容最后面的结尾是『/root/bin』, 所以你可以看到上面我删除的数据最终一定是『bin』,亦即是『:*bin』那个 * 代表通配符! 至于 % 与 %% 的意义其实与 # 及 ## 类似!这样理解否?
例题: 假设你是 root ,那你的 MAIL 变量应该是 /var/spool/mail/root 。假设你只想要保留最后面那个档名 (root), 前面的目录名称都不要了,如何利用 $MAIL 变量来达成? 答: 题意其实是这样『/var/spool/mail/root』,亦即删除掉两条斜线间的所有数据(最长符合)。 这个时候你就可以这样做即可:
相反的,如果你只想要拿掉文件名,保留目录的名称,亦即是『/var/spool/mail/root』 (最短符合)。但假设你并不知道结尾的字母为何,此时你可以利用通配符来处理即可,如下所示:
|
2、取代:
变量的测试与内容替换 |
在某些时刻我们常常需要『判断』某个变量是否存在,若变量存在则使用既有的配置,若变量不存在则给予一个常用的配置。
不过这还是有点问题!因为 username 可能已经被配置为『空字符串』了!果真如此的话,那你还可以使用底下的范例来给予 username 的内容成为 root 喔!
在大括号内有没有冒号『 : 』的差别是很大的!加上冒号后,被测试的变量未被配置或者是已被配置为空字符串时, 都能够用后面的内容 (本例中是使用 root 为内容) 来替换与配置!
如果你想要将旧变量内容也一起替换掉的话,那么就使用等号 (=) 吧!
那如果我只是想知道,如果旧变量不存在时,整个测试就告知我『有错误』,此时就能够使用问号『 ? 』的帮忙啦!
文章出自:,《鸟哥的linux私房菜》,请尊重原作者的劳动成果!