我正在尝试在终端之间交换环境变量并快速恢复它们。
我在 shell 中定义了两个函数 ( ~/.bashrc
):
save_env(){
mkdir -p ~/tmp
printenv > ~/tmp/env
}
load_env(){
source ~/tmp/env
}
;
除环境变量中有分号 ( ) 外,它们都按预期工作,例如
LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:
使用时load_env
出现如下错误
34:ln=01: command not found
36:mh=00:pi=40: command not found
33:so=01: command not found
我怎样才能解决这个问题?
;
不会是唯一有问题的字符。shell 语法中的任何特殊字符也会出现问题。|&<>*?[]~#'"\$^()
至少包括空格和换行符。printenv
(非标准命令)打印name=value
它自己接收的环境中的每个环境变量,后面跟一个换行符。它会打印这些名称和值。它不打算生成 shell 代码。事实上,它还会打印名称无法映射到 shell 变量的环境变量。它显然不会打印未导出到环境的 shell 变量,包括数组或关联变量,当然还有非变量 shell 参数,例如
$1
,$2
,$!
,$$
...具体就 shell 而言,它将打印用于导出导出函数
bash
的特殊环境变量。bash
例子:要保存导出到环境的 shell 变量,您可以使用
export -p
(标准,但它为给定 shell 生成的输出只能在同一个 shell(及其版本、相同的操作系统(libc)和语言环境)中使用)。例如,我们上面的例子:
这 3 个变量实际上是由 bash 本身在内部定义的。
OLDPWD
已导出,但在本例中未设置。请注意 bash 在输出中使用了
declare -x
而不是export
。这意味着当在函数内解释结果代码时,结果变量将是函数的本地变量。要解决这个问题,您可以设置以下选项posix
:但是请参阅如何
OLDPWD
导出但未设置或取消设置,因此在恢复时,其值将保持不变。对于您导出但未设置的任何变量,也会发生同样的情况。所以,你的
save_env
可能看起来像:和
load_env
:(
command
如果 bash 处于 POSIX 模式,则避免在出现错误时退出 shell)。local -
(非标准且从 Almquist shell 复制)要更改函数本地选项,需要相对较新版本的 bash。对于旧版本,您始终可以使用子 shell 而不是命令组作为函数主体save_env
:另请注意,bash 将选项设置存储在其
SHELLOPTS
变量中(参数的长选项变体$-
)。如果导出该变量(这不是明智之举),则该posix
选项最终将包含在 打印的值中export -p
。要打印所有变量(不仅仅是导出的变量)及其值,您可以
set
单独使用,但请注意它不包含属性信息(如导出、只读、整数……),并且在 bash 的情况下还包括函数。由于它还包括只读变量,因此在获取结果时也会收到错误。就像在 Korn shell 或 zsh 中一样,
typeset -p
可用于打印变量定义,包括它们的类型和属性,但就像export -p
不在模式下时一样posix
,输出将具有类似declare -- var="value"
当函数内的源创建函数本地变量时的内容。从 4.4 版开始,bash 还具有一个
${var@A}
扩展为可用于重新定义该变量的代码,并且可以与${!varname@A}
间接运算符一起使用,但它会给出一些混合输出:它将给出var='value'
一个没有属性的标量变量,但declare -x var='value'
除此之外(与上面相同的问题),并且对于空数组或关联给出declare -a var
/declare -A var
(自 5.1 起)而不是declare -a var=()
/declare -A var=()
(在以前的版本中根本没有任何内容)所以总体来说是相当没用的。使用 zsh 而不是 bash,您可以更好地控制要选择哪些变量以及如何转储它们。
zsh
有一个特殊的$parameters
关联数组,将变量名称映射到其类型和属性。例如,
print -raC2 -- ${(kv)parameters}
对列(交叉)上的该关联值的print
、k
eys 和v
alues输出如下内容:r
2
C
a
要仅打印既不是也不是隐藏的
scalar
变量的定义,您可以这样做:special
readonly
如果在函数内运行,它将
-g
在生成的typeset
命令行中添加一个选项¹(函数本地变量除外),以防止在函数内再次获取变量时使变量变为本地变量。1 bash
typeset
也有一个-g
选项,但是它将变量放置在最外层的作用域中,而不是避免将变量设置为本地变量(如果还没有的话),因此它相当无用。