用bash保存数据?

Lif*_*ake 3 bash shell

好的,所以我想知道是否有可能像bash中的变量一样保存.我正在写一个脚本,你建立像农场和矿山,我只是想知道是否有可能带回那些变量,即使我停止了程序,然后重新开始.所以,假设我已经建造了4个农场农场将是农场= 4,我能以某种方式带回这个变量吗?我知道如何制作一个你可以制作高分榜单的页面(我为猜谜游戏所做的那些.),但我不知道这是否有可能在bash中.

gni*_*urf 6

您可以使用该格式在文件中编写所有内容:

farm=4
myname=gniourf
Run Code Online (Sandbox Code Playgroud)

然后获取该文件:

#!/bin/bash

# Recover the saved states:
source file_where_i_saved_my_stuff

# Now you can recover all your variables!
echo "$farm"
echo "$myname"
Run Code Online (Sandbox Code Playgroud)

编辑

既然你想知道如何保存你的变量,这里有一个快速的提示,其中很多东西都没有在另一个答案中给出.

好吧,所以你想在文件中保存一些变量,并能够以后获取这个文件以恢复这些变量的值.当然,你会有很多变量,并且你不想明确写下你必须保存的所有变量的列表,这是容易出错和延迟的.我的意思是,没有人想要做以下事情:

cat <<EOF > file_where_i_saved_my_stuff
variable1=$variable1
variable2=$variable2
...
variable1000000=$variable1000000
EOF
Run Code Online (Sandbox Code Playgroud)

事实上,出于多种原因,您根本不想这样做.现在,我将解决这个问题:

该方法依赖于这种愚蠢的事(具有良好的bash实践和知识一起):命名所有你想要使用的前缀,例如,保存变量variable_i_want_to_save_,这样你就会有变量,如variable_i_want_to_save_number_of_farmsvariable_i_want_to_save_color_of_granny_dress等.不要将此前缀用于您不想保存的变量.

聪明的东西#1

bash有一个很棒的东西:你可以得到所有以某个前缀开头的变量的名称,如下所示:

"${!prefix@}"
Run Code Online (Sandbox Code Playgroud)

这将扩展为以prefix开头的所有已知变量的列表prefix.

因此,在我们的案例中,

for i in "${!variable_i_want_to_save_@}"; do
Run Code Online (Sandbox Code Playgroud)

将循环遍历以我们精彩前缀为前缀的所有变量的名称.那不是很好吗?

聪明的东西#2

如果我在以下情况:

a=1
b=2
variablename="a"
Run Code Online (Sandbox Code Playgroud)

如何获取变量的值,变量的名称是变量的值variablename?容易,使用"${!variablename}"构造.看:

$ a=1
$ b=2
$ variablename=a
$ echo "${!variablename}"
1
Run Code Online (Sandbox Code Playgroud)

${!prefix@}${!variablename}扩展都在解释壳牌参数扩展 Bash的参考的部分(您需要向下滚动一点到那里).

(破碎)解决方案

那么你就是一个破碎的解决方案,可以将变量保存在文件中,如下所示:

save_data_to_file() {
    for i in "${variable_i_want_to_save_@}"; do
        echo "$i=${!i}"
    done > file_where_i_saved_my_stuff
}
Run Code Online (Sandbox Code Playgroud)

这非常有效且很酷,但如果你的变量中有任何类型的空格或垃圾字符(可以(并且应该)出现),这真的很糟糕.噢亲爱的.

对你的好处是,bash有这个美好printf以其惊人的格式规范命令%q即会

以可以作为shell输入重用的方式引用参数

(我得到了这个help printf).这太棒了,它绝对棒极了,试试吧:

$ a=$'bonjour les amis !\ncomment ça va ?'
$ # You see, variable a has a lot of stupid characters:
$ echo "$a"
bonjour les amis !
comment ça va ?
$ # and printf does a wonderful job:
$ printf '%s=%q\n' a "$a"
a=$'bonjour les amis!\ncomment \303\247a va ?'
Run Code Online (Sandbox Code Playgroud)

你无法想象这样的好事.或者也许你可以,但请承认它真棒!

所以,在这里,您可以通过各种方式将变量保存在文件中:

save_data_to_file() {
    for i in "${!variable_i_want_to_save_@}"; do
        printf '%s=%q\n' "$i" "${!i}"
    done > file_where_i_saved_my_stuff
}
Run Code Online (Sandbox Code Playgroud)

请注意,获取此类外部文件会导致明显的安全问题,因此请务必小心使用此方法!


Gil*_*not 5

您可以将所有需要的变量保存在文件中(使用here-doc):

cat<<EOF>/path/to/file
var1="$var1"
var2="$var2"
EOF
Run Code Online (Sandbox Code Playgroud)

并重新创建以前的环境:

source /path/to/file
Run Code Online (Sandbox Code Playgroud)

要么

. /path/to/file
Run Code Online (Sandbox Code Playgroud)

说明

  • 如果您不必通过示例在循环中保存变量,那么放置here-doc的地方取决于您的代码,可以是最后一行
  • shebangsource之后放置命令的地方是你脚本的顶部

帮助说:

$ LANG=C help source
Run Code Online (Sandbox Code Playgroud)

source:source filename [arguments]从当前shell中的文件执行命令.

Read and execute commands from FILENAME in the current shell.  The
entries in $PATH are used to find the directory containing FILENAME.
If any ARGUMENTS are supplied, they become the positional parameters
when FILENAME is executed.

Exit Status:
Returns the status of the last command executed in FILENAME; fails if
FILENAME cannot be read.
Run Code Online (Sandbox Code Playgroud)

注意

如果由于某些原因需要动态生成带有变量名称模式匹配的文件:

  • 通过后缀: printf '%q\n' $(set | grep "suffix=") > save_file
  • 按前缀: printf '%q\n' $(set | grep "^prefix") > save_file

谢谢gniourf_gniourf的printf伎俩.