Skip to main content

set,env,export,declare 是如何操作shell变量的

wKevin
  • 定义一个环境变量用 set 还说 declar?
  • 已定义的环境变量为什么在脚本中不能使用?
  • set 和 env 导出的变量一样么?

如果这些问题存有疑惑,可以读一下此文。

首先啰嗦几句其他的:Linux 中 shell 和 Terminal 不是一回事,Terminal 是登录、调用、使用、管理 shell 的程序,几乎所有 Linux 发行版都会自带一个 Terminal,有些还会带多个。在 Terminal 上,可以用 Tab 页来创建、管理同时多个 shell 进程,还可以设置更符合自己美学要求的 UI。顺带安利一个强大的 Terminal:iTerm2, Linux 的可以用关键词 “best linux terminal” 来搜索。

创建一个 shell 进程,除了在本机上直接打开 Terminal 之外,还可以用远程电脑上的 Terminal(或其他工具)通过 ssh、telnet 进入 —— 前者叫“非登录式 shell 进程”,后者叫“登录式 shell 进程”。

执行一个 shell 进程,除了在 Terminal 上敲入一行,执行一行,看结果之外,还可以执行一个脚本,一次执行多个命令行 —— 前者叫“交互式 shell 进程”,后者叫“非交互式 shell 进程”。

在一个 shell 进程中敲入 shbash 可以创建一个当前 shell 进程的子进程,还有很多 shell 可以用,如:ash、csh、ksh、zsh…… 可以安装后使用。

OK,铺垫完毕,来看 shell 变量,即在 shell 进程(交互 or 非交互)中能够使用的。

Shell 除了特殊变量,根据作用域分为 3 种:

作用域函数内shell 进程内传递给 shell 子进程备注
称为本地变量局部环境变量全局环境变量使用较广泛
又称为函内变量进程内变量跨进程变量Kevin 命名
又称为局部变量全局变量环境变量算有些道理
又称为shell 变量shell 变量环境变量有些混淆视听
作用域说明仅在 shell 的函数内有效一个 shell 进程内有效,不传递给子进程传子不传父:某进程中定义的变量会传给子进程,不影响父进程;
改子不改父:在子进程中对变量的修改不影响父进程;
子进程可以与父进程使用不同的 shell(如:父进程 bash,子进程 ksh)
变量定义function func(){
local a=1
}
1.function func(){
A=1 #函数内不加local
}
2.B=1
1.export ABC=123
2.ABC=123;export ABC
3.declare -x ABC=123
变量来源用户定义用户定义1.大多来自以下文件中的 export 声明:
/etc/profile
~/.profile
~/.bash_profile
~/.bashrc
2.用户export声明
变量使用$a$A $B$ABC
变量查阅(单个)echo $Aecho $ABC
printenv ABC
变量查阅(列表)set==declareset==declare
env~=export
变量删除unsetunset
  • env ~= export: 只 list 全局环境变量
  • set == declare: list 全局环境变量、局部环境变量、function
  • set 只能查看、修改变量,不能定义变量
  • 环境变量声明脚本的说明
    • /etc/profile 每次用户登录是执行一次
    • ~/.profile 每次创建 shell 进程时执行一次
    • ~/.bashrc 每次新建 bash 进程会调用一次,所以 bash 子进程中会出现多次(其他 shell 子进程不会)该文件中定义的变量 —— so,变量尽量不要在该文件中定义,放到 ~/.profile 中定义。

最后,附录一下 Shell 特殊变量:

  • $0: 当前脚本的文件名(不带路经,带扩展名 .sh )xx.sh
  • $n: 返回第 n 个参数。( n>0 )
  • $#: 统计传入的变量个数 e.g. ./xx.sh p1 p2 输出 2
  • $*: 列出所有参数 。" $* " 整体列出
  • $@: 列出所有参数 。"$@" 一一列出
  • $?: 返回上一个命令执行的返回码
  • $$: 返回 pid
  • $!: 最后运行的后台 Process 的 pid
  • $-: 列出 Set 命令设定的 Flag