《鸟哥的Linux私房菜》之认识与学习BASH(Shell的变量功能)
10.2.2 变量的取用与设定:echo,变量设定规则,unset
- 变量的取用:echo
取变量通过echo,在变量前加上$读出,例如:echo $PATH
设定或修改变量的内容,直接用【等号(=)】连接变量和它的内容。
注意,在bash中,当一个变量的名称尚未设定的时候,预设的内容是【】的;而在某些shell中,去echo一个不存在的变量,可能会报错。 - 变量设定的规则
- 变量与变量内容可以用一个【等号(=)】来连接:
myname=achao - 等号两边不能直接接空格号:
myname=achao good 或 myname = achao - 变量名只能是英文字母和数字,而且不能使用数字开头:
2myname=achao - 变量名如有空格符可以使用双引号【"】或者单引号【’】将变量内容结合起来。
myname="achao good"双引号内的特殊字符如$等,可以保存其原有的特性:
var="path is $PATH
单引号中的特殊字符只显示为一般字符:
var=‘path is $PATH’ - 可以通过跳脱字符【\】,将特殊符号(如【Enter】、$、空格符、’等)变成一般字符
myname=achao\ good - 在一串指令的执行中,如果还需要额外的指令所提供的信息,可以使用反单引号【
指令
】或【$(指令)】 - 若该变量为扩增变量内容时,则可以使用"{变量名称},比如我们常见的:PATH=${PATH}:/home/bin
- 可以用export来使变量成为环境变量
export PATH - 可以使用unset来取消变量
unset myname
在我目前的shell下,去启动另一个新的shell,新的那个shell就是子程序。一般情况下,父程序的自定义变量是无法在子程序中使用的;但是通过export就可以将变量变为环境变量,就能够在子程序中使用。
10.2.3 环境变量的功能
环境变量可以帮我们达到很多功能,比如家目录的变换、提示字符的显示、执行文件搜索的路径等等。我们可以使用env和export来查阅当前shell环境中有多少默认的环境变量
- HOME 代表用户的家目录
- SHELL 告知这个环境使用的是哪个Shell程
- HISTSIZE 表示曾经下达过的指令的记录数量
- MAIL 当使用mail指令收信的时候,系统会去读取的邮件信箱文件
- PATH 执行文件搜寻的路径
- LANG 系统语言
- RANDOM 随机数变量
用set观察所有变量(含环境变量和自定义变量)
- PS1:(提示字符的设定)
- \d :可以显示日期格式【星期 月 日】
- \H :完整的主机名\h :仅取得主机名在第一个小数点之前的名字
- \t :显示时间(24小时格式)【HH:MM:SS】
- \T :显示时间(12小时格式)【HH:MM:SS】
- \A :显示时间(24小时格式)【HH:MM】
- @ :显示时间(12小时格式)【am/pm格式】
- \u :目前使用者的账号
- \v :BASH的版本信息
- \w :完整的工作目录名称
- \W :利用basename函数取的工作目录名称
- \# :下达的第几个指令
- \$ :提示字符,如果是root时,提示字符为#,否则就是$
$: (关于本shell的PID)
如果想知道shell的PID,echo $$
?:(关于上个执行指令的回传值)
如果上个指令执行正确,返回的是0才对,而如果出错,将会返回一个出错代码。
export :自定义变量转成环境变量
因为子程序会继承父程序的环境变量,子程序不会继承父程序的自定义变量。
10.2.4 影响显示结果的语系变量(locale)
当我们用man 【command】的方式来查询某个数据的说明文件时,该说明文档的内容可能因为我们使用的语言的不同而产生乱码,那么我们的Linux到底支持多少种语系呢?我们可以使用locale指令来进行查询。只要用户设定了LANG和或LC_ALL时,其他语系的变量都会被这两个变量取代!
10.2.5 变量的有效范围
我们基本上可以这样认为:
环境变量=全局变量
自定义变量=局部变量
为什么环境变量的数据可以被子程序引用?这是因为内存配置的关系!理论上是这样的:
- 当启动一个shell时,操作系统会分配一块内存给shell使用,使这个内存中的变量可以被子程序取用
- 如在父程序中利用export功能,可以让自定义变量的内容写到上述的内存区当中
- 当加载另一个shell时,子shell可以将父shell的环境变量所在的内存块导入到自己的环境变量中
10.2.6 变量键盘读取、数组和宣告:read,array,declare
我之前使用的设定变量功能,都是直接用指令列设定过来的,那可以直接让用户从键盘中输入吗?比如在我们执行某些程序过程中,会要求使用者输入“yes/no"之类的信息!此外,我吗也应该能宣告某个变量的属性,比如:这个变量是数字还是数组等等。
-
read
要想读取来自键盘输入的变量,使用read这个指令。
read [-pt] variable选项和参数:
-p : 后面可以接上提示字符
-t : 后面可以接上等到的【秒数】
read之后不加上任何参数,直接加上变量名,那么地下会出现一个空白行等待你的输入。 -
declare / typeset
declare 或 typeset是一样的功能,就是在【宣告变量的类型】
declare [-aixr] variable
参数和选项
- a : 将后面名为variable的变量定义成数组(array)类型
- i : 将后面名为variable的变量定义成整数数据类型
- x : 用法和export一样,将后面的variable变成环境变量
- t : 将变量设定为readonly类型,该变量不可被更改内容,也不能unset
在bash中默认类型为【字符串】,此外bash支持的数值运算,预设最多只能到达整数形态,例如1/3的结果为0。
使用【+】可以进行取消操作,如上面中使用【declare +x sum】来取消将其设置为全局变量操作。
但是如果你将某个变量设定为【只读】类型时,通常需要注销再登入才能复原该变量的类型。 -
数组(array)变量类型
目前我们的bash中只支持一维数组
一般建议直接使用${数组}的方式来进行读取数据。
10.2.7 与文件系统及程序的限制关系:ulimit
想象一个现实状况,一个Linux主机中登入了十个人,每个用户同时开启了100个文件,每个文件的大小为10MB,则在这样的情况下,主机需要1010010=10GB的内存,为了避免这个情况的发生,我们的bash可以限制用户的某些资源,包括可以开启的文件数量、可以使用的CPU时间、可以使用的内存总量等等。
ulimit [-SHacdfltu] [配额]
- H : hard limit :严格的设定,必定不能超过这个值
- S :soft limit :警告的设定,可以超过,但是会有警告信息
- a : 后面不加有任何选项和参数,可以列出所有的限制额度
- c :当某些程序发生错误时,系统可能会将该程序在内存中的信息写出文件(除错用),这种文件就被成为核心文件,此为限制每个核心文件的最大容量
- f :此shell可以建立的最大文件容量(一般可能设定为2GB)
- d :程序可以使用的最大断裂内存容量
- t :可以使用的最大CPU时间(单位为秒)
- u :单一用户可以使用的最大程序数量
想要复原ulimit的设定最简单的方法就是注销后再登入,否则就是需要重新设定ulimit设定才行。不过一般身份使用者如果以ulimit设定-f的文件的大小,那么他只能继续减小文件的容量,不能增加文件的容量。
10.2.8 变量内容的删除、取代和替换(Optional)
- 变量内容的删除和取代
【从最前面向右删除变量内容】
${variable#/*local/bin:} 删除模式
${variable#/*local/bin:} 代表从最前面开始向右删除,且删除最短的那个
${variable#/*local/bin:} 代表被删除的部分,从/开始
${variable##/*local/bin:} 使用##表示【删除最长的那个数据】
【从后面向前删除变量内容】
echo ${path%:*bin} 从最后面向前删除最短字符串
echo ${path%%:*bin} 从最后面向前删除最长字符串
【从字符串最前面替换变量内容】
echo ${path/sbin/SBIN} 其中两个/中间的字符串为旧字符串,后面的是新字符串
echo ${path//sbin/SBIN} 其中如果变成//则所有符合的内容都会被取代
【小结】 - 变量的测试与内容替换
关于上面的范例,我们可以这样理解:
new_var=${old_var-content} 【给予未设定变量的内容,已设定的内容无法更改】
new_var=${old_var:-root} 【更改已设定内容的变量】
如果旧变量不存在时,整个测试就告知我【有错误】,此时就能使用问号【?】