Bash Shell 使用「环境变量」来存储有关 Shell 会话和工作环境的信息。环境变量分为两类:
【注】有关子 Shell 和孩子 Shell 的详细介绍参见 LinuxShell父子关系概述。
环境变量区分大小写,系统环境变量基本都是使用全大写字母,以区别于用户自定义的环境变量,因此用户自定义的环境变量最好都使用小写。
查看全局变量可以使用 env
或 printenv
命令。
env # 查看所有全局变量
printenv # 查看所有全局变量
printenv <variable> # 查看单个全局变量 <variable>
【注】env
和 printenv
只会输出全局变量,而且也不会对输出的全局变量进行排序。
局部环境变量只能在定义它们的进程中可见。查看局部变量的列表有些复杂,Linux 系统并没有一个只显示局部环境变量的命令。可以使用 set
命令显示某个特定进程设置的所有环境变量,包括系统局部变量、系统全局变量和用户自定义环境变量。
set
【注】set
命令会将变量按照字母顺序进行排序,且只显示值非空的环境变量。除了输出所有的环境变量外,使用不带参数的 set
命令还会输出当前环境所有的函数。
本地环境变量只能在函数内部被定义和使用,它们只能在定义它们的函数内部以及子函数中可见。
创建环境变量时,变量名的命名需要遵守以下规则:
通过使用等号来设置局部环境变量,并给其赋值,值可以是数值或者字符串。基本格式如下:
var=value # var 为局部环境变量,value 为其值
Bash Shell 扩展了局部环境变量赋值语句,通过在赋值语句后接一条命令,则可以实现该局部变量仅在命令执行环境中有效,一旦命令执行完局部变量也将失效。
var=value command
创建全局环境变量的方法是先创建一个局部变量,再通过 export
命令导出到全局环境中。
var=value
export var
总而言之,即全局变量的增删改查都只是向下单层单向独立继承。
其实也好理解,因为不同进程之间的各个参数都是独立的,因此只有在创建子进程的时候存在父进程到子进程的变量继承,创建后两个进程之间的变量就是完全独立的,互不影响。
local
命令用于创建「本地环境变量」。其语法格式如下:
local OPTION VARIABLE=value
local
的选项参数 OPTION
同下文介绍的 declare
,但诸如 -x
参数是无效的。
读取环境变量时,直接在变量前加上 $
即可。
echo $HOME
{}
包裹变量名以明确变量名。a=foo
echo ${a}_file
${!varname}
语法来读取。var="USER"
echo ${!var}
在 Bash Shell 使用 unset
命令来删除环境变量。
unset var
在登入 Linux 系统启动一个 Bash Shell 时,默认情况下 Bash 会在几个文件中查找命令。这些文件称为「启动文件」或「环境文件」。Bash 检查的启动文件取决于你启动 Bash Shell 的方式。启动 Bash Shell 有三种方式:
而要让环境变量持久化便是将环境变量写入启动文件,这样每当启动 Bash Shell 后就会自动载入写入的环境变量从而达到持久化效果。关于这三种不同的 Shell 登录方式及其启动文件的详细介绍可参考 LinuxShell分类。
【注】有些 Linux 发行版使用了「可拆卸认证模块」(PAM),在这种情况下,PAM 文件会在 Bash Shell 启动之前处理,这些文件中也可能会包含环境变量。PAM 文件包括 /etc/environment
文件和 $HOME/.pam_environment
文件。PAM 更多相关信息可参考官方网址。
上文讲到环境变量都是单变量,其值可以是字符串和数值。而其实 Bash Shell 还提供了定义数组变量的功能。
array=(val1 val2 ... valn)
其中,array
为数组变量,使用 ()
来定义其值,值与值之间用空格分隔。
echo ${array[2]}
*
作为通配符作为索引值:echo ${array[*]}
【注】直接使用数组变量并不能查询到整个数组变量,而是只查询到其第一个元素值。和 C 语言中的数组类似,即数组变量指向的是数组的第一个元素。
echo $array
# 等价于
echo ${array[0]}
array[2]=newval3
array=(newval1 newval2 ... newvalm)
unset array[2]
【注】删除数组变量的单个元素后,虽然直接显示整个数组变量是没有被删除的元素,但如果专门查询该元素会发现,其实不是真的把该索引对应的数组元素剔除了,而是把它置空了,因此显示该元素时打印了空值,所以显示结果相看起来是没有该元素的。
unset array
Bash Shell 源自早期的 Unix Bourne Shell,因此继承了 Unix Bourne Shell 定义的一些默认的环境变量。
变量 | 说明 |
---|---|
CDPATH | 冒号分隔的目录列表,作为 cd 命令的搜索路径 |
HOME | 当前用户的主目录 |
IFS | Shell 用来将文本字符串分割成字段的一系列字符 |
当前用户收件箱的文件名(Bash Shell 会检查这个文件,看看有没有新邮件) | |
MAILPATH | 冒号分隔的当前用户收件箱的文件名列表(Bash Shell 会检查列表中的每个文件,看看有没有新邮件) |
OPTARG | getopts 命令处理的最后一个选项参数值 |
OPTIND | getopts 命令处理的最后一个选项参数的索引号 |
PATH | Shell 查找命令的目录列表,由冒号分隔 |
PS1 | Shell 命令行界面的主提示符 |
PS2 | Shell 命令行界面的次提示符 |
变量 | 说明 |
---|---|
BASH | 当前 Shell 实例的全路径名 |
BASH_ALIASES | 含有当前已设置别名的关联数组 |
BASH_ARGC | 含有传入子函数或 Shell 脚本的参数总数的数组变量 |
BASH_ARCV | 含有传入子函数或 Shell 脚本的参数的数组变量 |
BASH_CMDS | 关联数组,包含 Shell 执行过的命令的所在位置 |
BASH_COMMAND | Shell 正在执行的命令或马上就执行的命令 |
BASH_ENV | 若设置了该变量,每个 Bash 脚本会在运行前先尝试运行该变量定义的启动文件 |
BASH_EXECUTION_STRING | 使用 bash -c 选项传递过来的命令 |
BASH_LINENO | 含有当前执行的 Shell 函数的源代码行号的数组变量 |
BASH_REMATCH | 只读数组,在使用正则表达式的比较运算符 =~ 进行肯定匹配(positive match)时,包含了匹配到的模式和子模式 |
BASH_SOURCE | 含有当前正在执行的 Shell 函数所在源文件名的数组变量 |
BASH_SUBSHELL | 当前子 Shell 环境的嵌套级别(初始值是 0) |
BASH_VERSINFO | 含有当前运行的 Bash Shell 的主版本号和次版本号的数组变量 |
BASH_VERSION | 当前运行的 Bash Shell 的版本号 |
BASH_XTRACEFD | 若设置成了有效的文件描述符(0、1、2),则 set -x 调试选项生成的跟踪输出可被重定向。通常用来将跟踪输出到一个文件中 |
BASHOPTS | 当前启用的 Bash Shell 选项的列表 |
BASHPID | 当前 Bash 进程的 PID |
COLUMNS | 当前 Bash Shell 实例所用终端的宽度 |
COMP_CWORD | COMP_WORDS 变量的索引值,后者含有当前光标的位置 |
COMP_LINE | 当前命令行 |
COMP_POINT | 当前光标位置相对于当前命令起始的索引 |
COMP_KEY | 用来调用 Shell 函数补全功能的最后一个键 |
COMP_TYPE | 一个整数值,表示所尝试的补全类型,用以完成 Shell 函数补全 |
COMP_WORDBREAKS | Readline 库中用于单词补全的词分隔字符 |
COMP_WORDS | 含有当前命令行所有单词的数组变量 |
COMPREPLY | 含有由 Shell 函数生成的可能填充代码的数组变量 |
COPROC | 占用未命名的协进程的 I/O 文件描述符的数组变量 |
DIRSTACK | 含有目录栈当前内容的数组变量 |
EMACS | 设置为 t 时,表明 emacs Shell 缓冲区正在工作,而行编辑功能被禁止 |
ENV | 如果设置了该环境变量,在 Bash Shell 脚本运行之前会先执行已定义的启动文件(仅用于当 Bash Shell 以 POSIX 模式被调用时) |
EUID | 当前用户的有效用户 ID(数字形式) |
FCEDIT | 供 fc 命令使用的默认编辑器 |
FIGNORE | 在进行文件名补全时可以忽略后缀名列表,由冒号分隔 |
FUNCNAME | 当前执行的 Shell 函数的名称 |
FUNCNEST | 当设置成非零值时,表示所允许的最大函数嵌套级数(一旦超出,当前命令即被终止) |
GLOBIGNORE | 冒号分隔的模式列表,定义了在进行文件名扩展时可以忽略的一组文件名 |
GROUPS | 含有当前用户属组列表的数组变量 |
histchars | 控制历史记录扩展,最多可有 3 个字符 |
HISTCMD | 当前命令在历史记录中的编号 |
HISTCONTROL | 控制哪些命令留在历史记录列表中 |
HISTFILE | 保存 Shell 历史记录列表的文件名(默认是 .bash_history) |
HISTFILESIZE | 最多在历史文件中存多少行 |
HISTTIMEFORMAT | 如果设置了且非空,就用作格式化字符串,以显示 Bash 历史中每条命令的时间戳 |
HISTIGNORE | 由冒号分隔的模式列表,用来决定历史文件中哪些命令会被忽略 |
HISTSIZE | 最多在历史文件中存多少条命令 |
HOSTFILE | Shell 在补全主机名时读取的文件名称 |
HOSTNAME | 当前主机的名称 |
HOSTTYPE | 当前运行 Bash Shell 的机器 |
IGNOREEOF | Shell 在退出前必须收到连续的 EOF 字符的数量(如果这个值不存在,默认是 1) |
INPUTRC | Readline 初始化文件名(默认是 .inputrc) |
LANG | Shell 的语言环境类别 |
LC_ALL | 定义了一个语言环境类别,能够覆盖 LANG 变量 |
LC_COLLATE | 设置对字符串排序时用的排序规则 |
LC_CTYPE | 决定如何解释出现在文件名扩展和模式匹配中的字符 |
LC_MESSAGES | 在解释前面带有 $ 的双引号字符串时,该环境变量决定了所采用的语言环境设置 |
LC_NUMERIC | 决定着格式化数字时采用的语言环境设置 |
LINENO | 当前执行的脚本的行号 |
LINES | 定义了终端上可见的行数 |
MACHTYPE | 用「CPU-公司-系统」(CPU-company-system)格式定义的系统类型 |
MAPFILE | 一个数组变量,当 mapfile 命令未指定数组变量作为参数时,它存储了 mapfile 所读入的文本 |
MAILCHECK | Shell 查看新邮件的频率(以秒为单位,默认值是 60) |
OLDPWD | Shell 之前的工作目录 |
OPTERR | 设置为 1 时,Bash Shell 会显示 getopts 命令产生的错误 |
OSTYPE | 定义了 Shell 所在的操作系统 |
PIPESTATUS | 含有前台进程的退出状态列表的数组变量 |
POSIXLY_CORRECT | 设置了的话,Bash 会以 POSIX 模式启动 |
PPID | Bash Shell父进程的 PID |
PROMPT_COMMAND | 设置了的话,在命令行主提示符显示之前会执行这条命令 |
PROMPT_DIRTRIM | 用来定义当启用了 \w 或 \W 提示符字符串转义时显示的尾部目录名的数量。被删除的目录名会用一组英文句点替换 |
PS3 | select 命令的提示符 |
PS4 | 如果使用了 bash 的 -x 选项,在命令行之前显示的提示信息 |
PWD | 当前工作目录 |
RANDOM | 返回一个 0~32767 的随机数(对其的赋值可作为随机数生成器的种子) |
READLINE_LINE | 当使用 bind –x 命令时,存储 Readline 缓冲区的内容 |
READLINE_POINT | 当使用 bind –x 命令时,表示 Readline 缓冲区内容插入点的当前位置 |
REPLY | read 命令的默认变量 |
SECONDS | 自从 Shell 启动到现在的秒数(对其赋值将会重置计数器) |
SHELL | Bash Shell 的全路径名 |
SHELLOPTS | 已启用 Bash Shell 选项列表,列表项之间以冒号分隔 |
SHLVL | Shell 的层级,每次启动一个新 Bash Shell,该值增加 1 |
TIMEFORMAT | 指定了 Shell 的时间显示格式 |
TMOUT | select 和 read 命令在没输入的情况下等待多久(以秒为单位)。默认值为 0,表示无限长 |
TMPDIR | 目录名,保存 Bash Shell 创建的临时文件 |
UID | 当前用户的真实用户 ID(数字形式) |
特殊变量 | 说明 |
---|---|
$0 ~ $9 | 位置参数,$0 是命令名,$1 ~ $9 是命令参数 |
$# | 记录脚本运行时携带的命令参数个数 |
$* | 用双引号括起后,将所有命令参数当作单个单词保存,即看作一个整体 |
$@ | 用双引号括起后,将所有命令参数当作字符串中的多个独立单词保存,即看作多个个体 |
$? | 记录最近执行的前台程序的退出状态 |
$- | 记录了当前 Shell 的选项 |
$$ | 当前 Shell 的 PID |
$! | 记录最近执行的后台进程的 PID |
$_ | 记录上一个命令的最后一个参数 |
更多详细介绍参见下文小节。
$0
~ $9
0 ~ 9 为命令行的位置参数,0 是命令名,1 ~
$#
$#
记录了脚本运行时携带的命令参数个数。
$*
$@
【注】* 和 @ 的使用很容易混淆,为了更好地理解可以参见以下例子:
test.sh
:#!/bin/bash main() { echo 'MAIN sees ' $# ' args' } main $* main $@ main "$*" main "$@"
./test.sh 'a b c' d e
MAIN sees 5 args MAIN sees 5 args MAIN sees 1 args MAIN sees 3 args
$?
$?
记录了最近执行的前台程序的退出状态。
$-
$-
记录了当前 Bash Shell 的选项标志。Bash Shell 的选项标志是在启动时或以内建命令 set 指定的,或者是 shell 自身设置的(例如选项 -i
)。有关 Bash Shell 选项选项参数更详细介绍可参考 Advanced Bash-Scripting Guide 或官方手册 man bash
。
在本地直接查看 - 值可以发现其为 himBH,关于其详细解释可参见 What do the characters in the bash environment variable - mean?。
$$
$$
记录了当前 Shell 的 PID。需要注意的是,在当前 Shell 创建的子 Shell 中,指的仍然当前父 Shell 的 PID;而在孩子 Shell 中则是孩子 Shell 的 PID。这是因为子 Shell 继承了父 Shell 的所有环境变量,而孩子 Shell 只继承了父 Shell 的全局环境变量。详细介绍参见 LinuxShell父子关系概述。
$!
$!
记录了最近执行的后台进程的 PID。
declare
命令除了使用上文提到的简单创建变量的语法,Bash Shell 还提供了 declare
命令用来扩展变量定义语法。
declare
命令可以声明一些特殊类型的变量,即为变量设置一些限制。declare
命令还可以查看声明的变量和函数。declare
命名创建变量的语法格式如下:
declare OPTION VARIABLE=value
declare
命令的主要参数(OPTION
)如下:
-a
:声明数组变量。-f
:输出所有函数定义。-F
:输出所有函数名。-i
:声明整数变量。-l
:声明变量为小写字母。-p
:查看变量信息。-r
:声明只读变量。-u
:声明变量为大写字母。-x
:该变量输出为全局环境变量。declare
命令如果用在函数中,声明的变量只在函数内有效,等同于 local
命令。declare
命令不带任何参数时,输出当前环境所有的环境变量和函数,等同于不带任何参数的 set
命令。readonly
命令readonly
命令等同于 declare -r
,用来声明只读变量,不能改变边变量值,也不能 unset
变量。
readonly
命名创建变量的语法格式如下:
readonly OPTION VARIABLE=value
declare
命令的可选参数(OPTION
)如下:
-f
:声明的变量为函数名。-p
:打印出所有的只读变量。-a
:声明的变量为数组。参考资料来源: