Linux学习之十一、环境变量的功能

环境变量的功能

可以利用两个命令来查阅,分别是 env 与 export 呢!

范例一:列出目前的 shell 环境下的所有环境变量与其内容。

[root@www ~]# env

SHELL

告知我们,目前这个环境使用的 SHELL 是哪支程序? Linux 默认使用 /bin/bash 的啦!

HISTSIZE

这个与『历史命令』有关,亦即是, 我们曾经下达过的命令可以被系统记录下来,而记录的『笔数』则是由这个值来配置的

LANG

这个重要!就是语系数据啰~很多信息都会用到他, 举例来说,当我们在启动某些 perl 的程序语言文件时,

他会主动的去分析语系数据文件, 如果发现有他无法解析的编码语系,可能会产生错误喔!一般来说,

我们中文编码通常是 zh_TW.Big5 或者是 zh_TW.UTF-8,这两个编码偏偏不容易被解译出来,所以,有的时候,可能需要修订一下语系数据。

RANDOM

这个玩意儿就是『随机随机数』的变量啦!目前大多数的 distributions 都会有随机数生成器,那就是 /dev/random 这个文件。

[root@www ~]# declare -i number=$RANDOM*10/32768 ; echo $number

8   <== 此时会随机取出 0~9 之间的数值喔!

用 set 观察所有变量 (含环境变量与自定义变量)

[root@www ~]# set

一些较为重要的系统内定变量

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 时,提示字符为 # ,否则就是 $ 啰~

更改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 主要分为 32/64 位,其中 32 位又可分为 i386, i586, i686,而 64 位则称为 x86_64。

由于不同等级的 CPU 命令集不太相同,因此你的软件可能会针对某些 CPU 进行优化,以求取较佳的软件性能。

你可以在 x86_64 的硬件上安装 i386 的 Linux 操作系统,但是你无法在 i686 的硬件上安装 x86_64 的 Linux 操作系统

export: 自定义变量转成环境变量

如你想要让该变量内容继续的在子程序中使用,那么就请运行:

[root@www ~]# export 变量名称

影响显示结果的语系变量 (locale)

查看Linux支持的语言

[root@www ~]# locale -a

....(前面省略)....

zh_TW

zh_TW.big5     <==大五码的中文编码

zh_TW.euctw

zh_TW.utf8     <==万国码的中文编码

如何修订这些编码呢?

[root@www ~]# locale  <==后面不加任何选项与参数即可!

LANG=en_US                   <==主语言的环境

LC_CTYPE="en_US"             <==字符(文字)辨识的编码

LC_NUMERIC="en_US"           <==数字系统的显示信息

LC_TIME="en_US"              <==时间系统的显示数据

LC_COLLATE="en_US"           <==字符串的比较与排序等

LC_MONETARY="en_US"          <==币值格式的显示等

LC_MESSAGES="en_US"          <==信息显示的内容,如菜单、错误信息等

LC_ALL=                      <==整体语系的环境

默认的语系定义在哪里

[root@www ~]# cat /etc/sysconfig/i18n

LANG="zh_TW.UTF-8"

----------------------------

变量的有效范围

被 export 后的变量,我们可以称他为『环境变量』! 环境变量可以被子程序所引用,但是其他的自定义变量内容就不会存在于子程序中。

变量键盘读取、数组与宣告: read, array, declare

要读取来自键盘输入的变量,就是用 read 这个命令

[root@www ~]# read [-pt] variable

选项与参数:

-p  :后面可以接提示字符!

-t  :后面可以接等待的『秒数!』这个比较有趣~不会一直等待使用者啦!

范例一:让用户由键盘输入一内容,将该内容变成名为 atest 的变量

[root@www ~]# read atest

This is a test        <==此时光标会等待你输入!请输入左侧文字看看

[root@www ~]# echo $atest

This is a test          <==你刚刚输入的数据已经变成一个变量内容!

范例二:提示使用者 30 秒内输入自己的大名,将该输入字符串作为名为 named 的变量内容

[root@www ~]# read -p "Please keyin your name: " -t 30 named

Please keyin your name: VBird Tsai   <==注意看,会有提示字符喔!

[root@www ~]# echo $named

VBird Tsai        <==输入的数据又变成一个变量的内容了!

-------------------------

declare / typeset

declare 或 typeset 是一样的功能,就是在『宣告变量的类型』

[root@www ~]# declare [-aixr] variable

选项与参数:

-a  :将后面名为 variable 的变量定义成为数组 (array) 类型

-i  :将后面名为 variable 的变量定义成为整数数字 (integer) 类型

-x  :用法与 export 一样,就是将后面的 variable 变成环境变量;

-r  :将变量配置成为 readonly 类型,该变量不可被更改内容,也不能 unset

范例一:让变量 sum 进行 100+300+50 的加总结果

[root@www ~]# sum=100+300+50

[root@www ~]# echo $sum

100+300+50  <==咦!怎么没有帮我计算加总?因为这是文字型态的变量属性啊!

[root@www ~]# declare -i sum=100+300+50

[root@www ~]# echo $sum

[root@www ~]# 450

变量类型默认为『字符串』,所以若不指定变量类型

bash 环境中的数值运算,默认最多仅能到达整数形态,所以 1/3 结果是 0;

范例二:将 sum 变成环境变量

[root@www ~]# declare -x sum

[root@www ~]# export | grep sum

declare -ix sum="450"  <==果然出现了!包括有 i 与 x 的宣告!

范例三:让 sum 变成只读属性,不可更动!

[root@www ~]# declare -r sum

[root@www ~]# sum=tesgting

-bash: sum: readonly variable  <==老天爷~不能改这个变量了!

范例四:让 sum 变成非环境变量的自定义变量吧!

[root@www ~]# declare +x sum  <== 将 - 变成 + 可以进行『取消』动作

[root@www ~]# declare -p sum  <== -p 可以单独列出变量的类型

declare -ir sum="450" <== 看吧!只剩下 i, r 的类型,不具有 x 啰

数组 (array) 变量类型

我有一个数组名为 var ,而这个数组的内容为 var[1]=小明, var[2]=大明, var[3]=好明 ....

等等,那个 index 就是一些数字啦,重点是用中刮号 ([ ]) 来配置的

范例:配置上面提到的 var[1] ~ var[3] 的变量。

[root@www ~]# var[1]="small min"

[root@www ~]# var[2]="big min"

[root@www ~]# var[3]="nice min"

[root@www ~]# echo "${var[1]}, ${var[2]}, ${var[3]}"

small min, big min, nice min

-----------------------------------

变量内容的删除、取代与替换

变量内容的删除与取代

变量的内容可以很简单的透过几个咚咚来进行删除喔!我们使用 PATH 这个变量的内容来做测试好了。

请你依序进行底下的几个例子来玩玩,比较容易感受的到鸟哥在这里想要表达的意义:

范例一:先让小写的 path 自定义变量配置的与 PATH 内容相同

[root@www ~]# path=${PATH}

[root@www ~]# echo $path

/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:

/usr/sbin:/usr/bin:/root/bin  <==这两行其实是同一行啦!

范例二:假设我不喜欢 kerberos,所以要将前两个目录删除掉,如何显示?

[root@www ~]# echo ${path#/*kerberos/bin:}

/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin

${variable#/*kerberos/bin:}

上面的特殊字体部分是关键词!用在这种删除模式所必须存在的

${variable#/*kerberos/bin:}

这就是原本的变量名称,以上面范例二来说,这里就填写 path 这个『变量名称』啦!

${variable#/*kerberos/bin:}

这是重点!代表『从变量内容的最前面开始向右删除』,且仅删除最短的那个

${variable#/*kerberos/bin:}

代表要被删除的部分,由于 # 代表由前面开始删除,所以这里便由开始的 / 写起。

需要注意的是,我们还可以透过通配符 * 来取代 0 到无穷多个任意字符

以上面范例二的结果来看, path 这个变量被删除的内容如下所示:

/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:

/usr/sbin:/usr/bin:/root/bin  <==这两行其实是同一行啦!

范例三:我想要删除前面所有的目录,仅保留最后一个目录

[root@www ~]# echo ${path#/*:}

/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:

/root/bin     <==这两行其实是同一行啦!

# 由于一个 # 仅删除掉最短的那个,因此他删除的情况可以用底下的删除线来看:

# /usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:

# /usr/sbin:/usr/bin:/root/bin  <==这两行其实是同一行啦!

[root@www ~]# echo ${path##/*:}

/root/bin

# 嘿!多加了一个 # 变成 ## 之后,他变成『删除掉最长的那个数据』!亦即是:

# /usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:

# /usr/sbin:/usr/bin:/root/bin  <==这两行其实是同一行啦!

非常有趣!不是吗?因为在 PATH 这个变量的内容中,每个目录都是以冒号『:』隔开的, 所以要从头删除掉目录就是介于斜线 (/) 到冒号 (:) 之间的数据!

但是 PATH 中不止一个冒号 (:) 啊! 所以 # 与 ## 就分别代表:

# :符合取代文字的『最短的』那一个;

##:符合取代文字的『最长的』那一个

范例四:我想要删除最后面那个目录,亦即从 : 到 bin 为止的字符串

[root@www ~]# echo ${path%:*bin}

/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:

/usr/sbin:/usr/bin  <==注意啊!最后面一个目录不见去!

# 这个 % 符号代表由最后面开始向前删除!所以上面得到的结果其实是来自如下:

# /usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:

# /usr/sbin:/usr/bin:/root/bin  <==这两行其实是同一行啦!

范例五:那如果我只想要保留第一个目录呢?

[root@www ~]# echo ${path%%:*bin}

/usr/kerberos/sbin

# 同样的, %% 代表的则是最长的符合字符串,所以结果其实是来自如下:

# /usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:

# /usr/sbin:/usr/bin:/root/bin  <==这两行其实是同一行啦!

由于我是想要由变量内容的后面向前面删除,而我这个变量内容最后面的结尾是『/root/bin』, 所以你可以看到上面我删除的数据最终一定是『bin』,亦即是『:*bin』那个 * 代表通配符!

至于 % 与 %% 的意义其实与 # 及 ## 类似!这样理解否?

例题:

假设你是 root ,那你的 MAIL 变量应该是 /var/spool/mail/root 。假设你只想要保留最后面那个档名 (root), 前面的目录名称都不要了,如何利用 $MAIL 变量来达成?

答:

题意其实是这样『/var/spool/mail/root』,亦即删除掉两条斜线间的所有数据(最长符合)。 这个时候你就可以这样做即可:

[root@www ~]# echo ${MAIL##/*/}

相反的,如果你只想要拿掉文件名,保留目录的名称,亦即是『/var/spool/mail/root』 (最短符合)。但假设你并不知道结尾的字母为何,此时你可以利用通配符来处理即可,如下所示:

[root@www ~]# echo ${MAIL%/*}

了解了删除功能后,接下来谈谈取代吧!继续玩玩范例六啰!

范例六:将 path 的变量内容内的 sbin 取代成大写 SBIN:

[root@www ~]# echo ${path/sbin/SBIN}

/usr/kerberos/SBIN:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:

/usr/sbin:/usr/bin:/root/bin

# 这个部分就容易理解的多了!关键词在于那两个斜线,两斜线中间的是旧字符串

# 后面的是新字符串,所以结果就会出现如上述的特殊字体部分啰!

[root@www ~]# echo ${path//sbin/SBIN}

/usr/kerberos/SBIN:/usr/kerberos/bin:/usr/local/SBIN:/usr/local/bin:/SBIN:/bin:

/usr/SBIN:/usr/bin:/root/bin

# 如果是两条斜线,那么就变成所有符合的内容都会被取代喔!

总结:

变量配置方式 说明

${变量#关键词}  若变量内容从头开始的数据符合『关键词』,则将符合的最短数据删除

${变量##关键词} 若变量内容从头开始的数据符合『关键词』,则将符合的最长数据删除

${变量%关键词} 若变量内容从尾向前的数据符合『关键词』,则将符合的最短数据删除

${变量%%关键词} 若变量内容从尾向前的数据符合『关键词』,则将符合的最长数据删除

${变量/旧字符串/新字符串}  若变量内容符合『旧字符串』则『第一个旧字符串会被新字符串取代』

${变量//旧字符串/新字符串}  若变量内容符合『旧字符串』则『全部的旧字符串会被新字符串取代』

---------------------------

变量的测试与内容替换

在某些时刻我们常常需要『判断』某个变量是否存在,若变量存在则使用既有的配置,若变量不存在则给予一个常用的配置。

我们举底下的例子来说明好了,看看能不能较容易被你所理解呢!

范例一:测试一下是否存在 username 这个变量,若不存在则给予 username 内容为 root

[root@www ~]# echo $username

<==由于出现空白,所以 username 可能不存在,也可能是空字符串

[root@www ~]# username=${username-root}

[root@www ~]# echo $username

root       <==因为 username 没有配置,所以主动给予名为 root 的内容。

[root@www ~]# username="vbird tsai" <==主动配置 username 的内容

[root@www ~]# username=${username-root}

[root@www ~]# echo $username

vbird tsai <==因为 username 已经配置了,所以使用旧有的配置而不以 root 取代

new_var=${old_var-content}

新的变量,主要用来取代旧变量。新旧变量名称其实常常是一样的

new_var=${old_var-content}

这是本范例中的关键词部分!必须要存在的哩!

new_var=${old_var-content}

旧的变量,被测试的项目!

new_var=${old_var-content}

变量的『内容』,在本范例中,这个部分是在『给予未配置变量的内容』

不过这还是有点问题!因为 username 可能已经被配置为『空字符串』了!果真如此的话,那你还可以使用底下的范例来给予 username 的内容成为 root 喔!

范例二:若 username 未配置或为空字符串,则将 username 内容配置为 root

[root@www ~]# username=""

[root@www ~]# username=${username-root}

[root@www ~]# echo $username

<==因为 username 被配置为空字符串了!所以当然还是保留为空字符串!

[root@www ~]# username=${username:-root}

[root@www ~]# echo $username

root  <==加上『 : 』后若变量内容为空或者是未配置,都能够以后面的内容替换!

Linux学习之十一、环境变量的功能

测试:先假设 str 不存在 (用 unset) ,然后测试一下减号 (-) 的用法:

[root@www ~]# unset str; var=${str-newvar}

[root@www ~]# echo var="$var", str="$str"

var=newvar, str=        <==因为 str 不存在,所以 var 为 newvar

测试:若 str 已存在,测试一下 var 会变怎样?:

[root@www ~]# str="oldvar"; var=${str-newvar}

[root@www ~]# echo var="$var", str="$str"

var=oldvar, str=oldvar  <==因为 str 存在,所以 var 等于 str 的内容

测试:先假设 str 不存在 (用 unset) ,然后测试一下等号 (=) 的用法:

[root@www ~]# unset str; var=${str=newvar}

[root@www ~]# echo var="$var", str="$str"

var=newvar, str=newvar  <==因为 str 不存在,所以 var/str 均为 newvar

测试:如果 str 已存在了,测试一下 var 会变怎样?

[root@www ~]# str="oldvar"; var=${str=newvar}

[root@www ~]# echo var="$var", str="$str"

var=oldvar, str=oldvar  <==因为 str 存在,所以 var 等于 str 的内容

测试:若 str 不存在时,则 var 的测试结果直接显示 "无此变量"

[root@www ~]# unset str; var=${str?无此变量}

-bash: str: 无此变量    <==因为 str 不存在,所以输出错误信息

测试:若 str 存在时,则 var 的内容会与 str 相同!

[root@www ~]# str="oldvar"; var=${str?novar}

[root@www ~]# echo var="$var", str="$str"

var=oldvar, str=oldvar  <==因为 str 存在,所以 var 等于 str 的内容

上一篇:linux学习笔记:关于环境变量


下一篇:python中BeautifulSoup库中find函数