Cal*_*leb 14
警告:使用这些解决方案中的任何一个,您需要意识到您相信数据文件的完整性是安全的,因为它们将作为脚本中的 shell 代码执行。保护它们对脚本的安全至关重要!
是的,在 bash 和 zsh 中,您都可以使用typeset内置-p函数和参数以易于检索的方式序列化变量的内容。输出格式是这样的,你可以简单地source输出来取回你的东西。
# You have variable(s) $FOO and $BAR already with your stuff
typeset -p FOO BAR > ./serialized_data.sh
Run Code Online (Sandbox Code Playgroud)
您可以稍后在脚本中或完全在另一个脚本中像这样恢复您的东西:
# Load up the serialized data back into the current shell
source serialized_data.sh
Run Code Online (Sandbox Code Playgroud)
这将适用于 bash、zsh 和 ksh,包括在不同 shell 之间传递数据。Bash 将把它转换成它的内置declare函数,而 zsh 用它来实现它,typeset但因为 bash 有一个别名,它可以以任何一种方式工作,我们typeset在这里使用它以实现 ksh 兼容性。
上面的实现真的很简单,但是如果你经常调用它,你可能想要给自己一个实用函数来使它更容易。此外,如果您尝试将上述内容包含在自定义函数中,您将遇到变量作用域的问题。此版本应消除这些问题。
注意所有这些,为了保持庆典/ zsh的交叉兼容性,我们将在固定的两种情况typeset,并declare因此代码应该在一个或两个壳工作。这会增加一些体积和混乱,如果您只为一个或另一个 shell 执行此操作,则可以消除这些问题。
为此使用函数(或包括其他函数中的代码)的主要问题是,该typeset函数生成的代码在从函数内部返回到脚本中时,默认为创建局部变量而不是全局变量。
这可以通过几种黑客之一来修复。我最初尝试解决这个问题是解析序列化过程的输出sed以添加-g标志,以便创建的代码在重新输入时定义一个全局变量。
serialize() {
typeset -p "$1" | sed -E '0,/^(typeset|declare)/{s/ / -g /}' > "./serialized_$1.sh"
}
deserialize() {
source "./serialized_$1.sh"
}
Run Code Online (Sandbox Code Playgroud)
请注意,时髦的sed表达式仅匹配第一次出现的 'typeset' 或 'declare' 并添加-g为第一个参数。必须只匹配第一次出现,因为正如Stéphane Chazelas在评论中正确指出的那样,否则它也会匹配序列化字符串包含文字换行符后跟单词声明或排版的情况。
除了纠正我的初步分析失礼,斯特凡还提出一个较不脆的方式来破解这不仅侧步骤,解析字符串的问题,但可能是一个有用的钩子使用的包装功能重新定义了行动,以添加额外的功能在重新获取数据时采用。这假设您没有使用声明或排版命令玩任何其他游戏,但在您将此功能作为您自己的另一个功能的一部分或您无法控制正在写入的数据以及是否-g添加了标志。也可以使用别名完成类似的操作,请参阅Gilles 的实现答案。
为了使结果更有用,我们可以通过假设参数数组中的每个单词都是一个变量名来迭代传递给我们函数的多个变量。结果变成了这样:
serialize() {
for var in $@; do
typeset -p "$var" > "./serialized_$var.sh"
done
}
deserialize() {
declare() { builtin declare -g "$@"; }
typeset() { builtin typeset -g "$@"; }
for var in $@; do
source "./serialized_$var.sh"
done
unset -f declare typeset
}
Run Code Online (Sandbox Code Playgroud)
使用任一解决方案,用法如下所示:
# Load some test data into variables
FOO=(an array or something)
BAR=$(uptime)
# Save it out to our serialized data files
serialize FOO BAR
# For testing purposes unset the variables to we know if it worked
unset FOO BAR
# Load the data back in from out data files
deserialize FOO BAR
echo "FOO: $FOO\nBAR: $BAR"
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6247 次 |
| 最近记录: |