Linux 中变量的取用与设定
优质博文:IT-BLOG-CN
Linux是一个多人多任务的环境,每个人登录系统都能取得一个 bash shell,每个人都能够使用 bash 下达 mail 这个指令来接收自己的邮箱等等。问题是,bash 如何得知你的邮箱是那个文件?这就需要『变量』的帮助。
一、什么是变量
【1】变量的可变性与方便性:简单的说,变量就是让一个特定的字符串代表不固定的内容。例如,每个账号的邮件预设是以MAIL这个变量来进行存取的。当 zzx 用户登录时,他便会去MAIL 这个变量,而这个变量的内容其实是 /var/spool/mail/zzx ,那如果 bird登录,他的变量MAIL的内容就是 /var/spool/mail/bird 。而我们使用信件读取指令 mail 来读取自己的邮箱信件。
【2】影响 bash 环境操作的变量:例如 PATH 变量,你能不能在任何目录下执行某个指令,与 PATH 这个变量有很大关系。例如你下达 ls 这个指令时,系统就是通过 PATH 这个变量里面的内容所记录的路径顺序来搜索指令的。如果搜索完 PATH 变量内的路径还找不到 ls 这个指令时,就会在屏幕上显示『 command not found 』的错误讯息了。在Linux System 下,所有的线程都是需要一个执行码,当正确登入Linux后,你就有一个 bash 执行程序,也才真正的经由 bash 来跟系统沟通。由于系统需要一些变量来提供他自己数据的存取(或者是一些环境的设定参数值,例如是否要显示彩色等等),所以就有一些所谓的『环境变量』需要来读入系统中,这些环境例如 PATH、HOME、MAIL、SHELL等等。为了区别与自定义变量的不同,环境变量通常以大写字符来表示。
【3】脚本程序设计(shell script)的好帮手:在个人设定方面,例如我们要写一个大型 script 时,有些数据可能由于用户习惯的不同而有差异,比如说路径,由于路径在 script 被使用的相当多,如果下次换一部主机,都要修改 script 里面的所有路径,那一定很low,这个时候就使用变量,而该变量的定义写在最前面,后面相关的路径名称都以变量来取代,那到时候只需要修改一行就等于修改了全部路径,相当方便。
二、变量的取用与设定
【1】变量的取用(echo) :利用 echo 就能够读取变量,只需要在变量前加上$符号,或者用${变量} 的方式读取内容。
【2】变量与变量内容之间如何设定与修改:用等号(=)连接变量与他的内容就好。
【3】变量的设定规则:①、等号两边不能直接接空格符。
②、变量名称只能是英文字母与数字,但是开头字符不能时数字。
③、变量内容若有空格符可使用双引号『"』或单引号『'』将变量内容结合起来。
④、可以使用跳脱字符『 \ 』将特殊符号(如:[Enter],$,\ ,空格符,' 等)
⑤、变量值是一串指令所提供的信息时,可以使用反单引号『`指令` 』或『$(指令) 』,例如想要取核心版本:
⑥、若该变量为扩展变量内容时,则可用 "$变量名称" 或 ${变量} 累加内容,如下:
⑦、若该变量需要在其他子程序执行,则需要 export 来使变量编程环境变量:『 export 变量名 』
⑧、通常大写的变量是系统默认的变量,自定义的变量一般都为小写。(规则,不遵守也行)
⑨、取消变量的方法使用:unset
三、环境变量的功能
【1】用 env 观察环境变量与常见环境变量说明:列出目前的 shell 环境下的所有环境变量与其内容。
env 是 environment(环境)的简写,如下部分环境变量。如果使用 export 也会是一样的内容。下面对环境变量进行介绍:
● HOME:代表用户的家目录。我们可以通过 cd ~ 去家目录。有很多程序都可能会取用到这个变量的值。
● SHELL:当前使用的 SHELL 是哪只程序,Linux预设使用 /bin/bash 。
● MAIL:当我们使用 mail 这个指令在收信时,系统会去读取邮件邮箱文件(mailbox)。
● HISTSIZE:这个与『历史命令』有关,我们曾下达过的指令可以被系统记录下来,而记录的『笔数』则是由这个值来设定的。
● PATH:就是执行文件搜索的路径,目录与目录之间以冒号分割,由于文件的搜索是依序由 PATH 的变量内的目录来查询的,所以,目录的顺序也是很重要的。
● LANG:这个比较重要,很多讯息都会用到它,例如:当我们启动某些 Perl 的程序语言文件时,他会主动的去分析语系数据文件,如果发现他无法解析的编码语系,就可能产生错误。
● RANDOM:随机数的变量,目前大多数 distributions 都会有随机数生成器,那就是 /dev/random 文件,在BASH环境下,这个RANDOM变量的内容,介于0~32767之间。如果要去0~9之间的数值,利用 declare 宣告数值类型,如下:
【2】用 set 观察所有变量(含环境变量与自定义变量):bash 可不只有环境变量,还有一些与 bash 操作接口有关的变量,以及用户自己定义的变量存在的。可通过 set 指令查看,set 除了环境变量之外,还会将其他在 bash 内的变量统统显示出来。
【3】PS1(提示字符的设定):命令提示符,当我们每次按下 Enter 键去执行某个指令后,最后要在此出现提示字符时,就会去主动读取这个变量值了,例如我本机的 PS1='[\u@\h \W]\$ ' 显示的是一种特殊符号,这些特殊符号可以显示不同的信息,每个distribution 的 bash 默认的 PS1 变量内容可能有差异,但不要紧,可以通过 man bash 查询PS1的相关说明,以理解底下的一些符号的意义。
✔ \d:可显示出『星期 月 日』的日期格式,如:“Mon Feb 2”
✔ \H:完整的主机名。
✔ \h:仅取主机在第一个小数点之前的名字。
✔ \t:显示时间,为24小时格式的『HH:MM:SS』
✔ \T:显示时间,为12小时格式的『HH:MM:SS』
✔ \A:显示时间,为24小时格式的『HH:MM』
✔ \@:显示时间,为12小时格式的『am/pm』
✔ \u:目前使用者的账号名称
✔ \v:BASE 的版本信息
✔ \w:完整的工作目录名称,由根目录写起的目录名称,所以仅会列出最后一个目录名。
✔ \#:下达的第几个指令
✔ \$:提示字符,如果是 root 的话,提示字符为 # ,否则为 $
CentOS预设的 PS1 内容:PS1='[\u@\h \W]\$ ',这个反斜杠后的数据为 PS1 的特殊功能,与 bash 的变量设定没有关系,现在我们应该都清楚为什么我的命令提示符是:『root@learnVM 桌面』,我们也可以修改自己的命令提示符:
【4】$(关于本 shell 的PID):钱字号本身也是个变量,表示当前 Shell 的线程代号,既所谓的PID(Process ID)。想要知道自己 shell 的 PID 可以通过 echo $$ 获取 PID 号码。
【5】?(关于上个执行指令的回传值):问号也是一个特殊的变数,在 bash 中这个变量很重要,表示上一个执行的指令所回传的值,当执行某指令时,这些指令都会回传一个执行后的代码。一般来说,如果成功的执行该指令,则会回传一个 0 值,如果执行过程发生错误,就会回传『错误代码』,一般就是以非为0的数值来取代。
【6】export(自定义变量转成环境变量):环境变量与自定义变量的区别,就是该变量能够被子程序继续引用的就是环境变量,反之则为自定义变量。简单介绍下子程序与父程序:当登录Linux后,会获取一个 bash(独立的程序),这个程序的识别使用的是一个称为程序标识符 PID 。接下来在 bash 底下所下达的任何指令都是由这个 bash 所衍生的,那些被下达的指令被称为子程序。
如果下达 export 指令就会将所有的『环境变量』绣出来:
四、影响显示结果的语系变量(locale)
当我们使用 man command 的方式去查询某个数据的说明文件时,该说明文档的内容可能会因为我们使用的语系不同而产生乱码。另外,利用 ls 查询文件的时间时,也可能会有乱码出现在时间部分。这个问题其实就是语系的问题。目前大多数的Linux系统都支持万国码了,也支持大部分的国家语系。我们可以通过 locale 指令查询自己的Linux支持多少语系。
正体中文语系至少支持了两种以上的编码,一种是目前还是很常见的 big5 ,另一种则是越来越热门的 utf-8 编码。我们可以通过以下逐一设定每个语系有关的数据变量,但事实是, 如果其他语系变量都没设置,且你有设置 LANG 或者是 LC_ALL 时,则其他的语系变量就会被这两个变量所取代!这也是为什么在Linux当中,通常说仅设定 LANG 或 LC_ALL 两个变量而已。在Linux主机的终端机接口(tty1~tty6)的环境下,如果设定『 LANG=zh_TW.utf8 』这个设定值生效后,使用 man 或者其他讯息输出时,都会出现一堆乱码,尤其是 ls -l 这个参数。Linux 主机的终端机接口环境下是无法显示像中文这么复杂的编码文字,所以就会产生乱码了。
五、变量的有效范围
变量也有使用的范围,则『变量』可否被引用与 export 有关。被 export 后的变量为『环境变量』。为什么环境变量的数据可以被子程序所引用,是因为内存配置的关系。
✔ 当启动一个 shell ,操作系统会分配一记忆区块给 shell 使用,此内存内之变量可让子程序取用。
✔ 若在父程序中利用 export 功能,可以让自定义变量的内容写到上述的记忆区块当中(环境变量)
✔ 当加载另一个 shell 时,子 shell 可以将父 shell 的环境变量所在的记忆区块导入自己的环境变量区块中。
六、变量键盘读取、数组与宣告(read、array、declare)
除了提到的变量设定功能,我们也可以通过键盘输入。就类似于我们执行某些程序时,会提示使用这输入 “yes/no” 之类的讯息。我们还可以宣告这个变量的属性,例如:数组或者是数字等等。
✔ read:读取来自键盘输入的变量。这个指令最常被用在 shell script 的撰写当中,想要跟使用者对谈就使用该指令。
✔ declare/typeset:宣告变量的类型。如果使用 declare 后面并没有接任何参数,那么 bash 就会主动将所有的变量名称与内容统统叫出来,就好像使用 set 一样。
由于在默认的情况底下 bash 对于变量有几个基本的定义:
● 变量类型默认为『字符串』,所以若不指定变量类型,则 1+2 为一个『字符串』而不是『计算式』。
● bash 环境中的数值运算,预设最多仅能达到整数形态,所以 1/3 结果是 0 ;
如果需要非字符串类型的变量,那就得要进行变量的宣告才行。如下继续接受 declare 功能。
需要注意的是,如果不小心将变量设定为『只读』,通常得要注销再登入才能复原该变量的类型。
✔ 数组(array)变量类型:var[index]=content:表示数组名为var,我们假定数组的内容为 var[1]=1,var[2]=2,var[3]=3等等,那么index就是一些数字。
七、与文件系统及程序的限制关系(ulimit)
我们知道 Linux 可以同时登陆十个人,如果同时启动十个文件每个文件的大小约 10 MBytes,主机的内存就需要10*100*10= 10000MBytes=10GBytes,系统就会挂点。为了要预防这个情况的发生,所以我们的 bash 是可以『限制用户的某些系统资源』的,包括可以开启的文件数量,可以使用的CPU时间,可以使用内存总量等等。可以用 ulimit 进行设置。
范例:列出你目前身份(假设为一般账号)的所有限制数据数值
想要复原 ulimit 的设定最简单的方法就是注销再登入,否则就是得要重新以 ulimit 设定才行。需要注意的是,一般身份使用者如果要以 ulimit 设定 -f 的文件大小,那么他『只能继续减小文件容量,不能增加文件容量』。
八、变量内容的删除、取代与替换(Optional)
【1】变量内容的删除与取代:具体举例说明:
(*)表示通配符,取 0 到无穷多个任意字符。从上面 的案例可以看出删除了5之前的所有元素。上面的一个 # 表示删掉最短的那个,那么两个 ## 表示删除最长的那个数据。那么除了上述从前面开始删除 # 之外,还有重后面开始删除的 % 。上述取掉实例中,两个斜线中间的是旧字符串,后面的是新字符串。那么两个双斜线表示的是替换所有符号条件的内容。
【2】变量的测试与内容替换:通常我们会判断某变量是否存在,如存在使用以有的,若不存在则给予一个常用的设定。举例:
在大括号内冒号【:】的作用,被测试的变量如果设定为空字符串时,就可以用*-root中的 root 来替换设定的空字符串的值:
变量设定方式 | str 没有设定 | str 为空字符串 | str 已设定非为空字符串 |
var=${str-expr} | var=expr | var= | var=$str |
var=${str:-expr} | var=expr | var=expr | var=$str |
var=${str+expr} | var= | var=expr | var=expr |
var=${str:+expr} | var= | var= | var=expr |
var=${str=expr} |
str=expr var=expr |
str不变 var= |
str不变 var=$str |
var=${str:=expr} |
str=expr var=expr |
str=expr var=expr |
str不变 var=$str |