4

好的,所以我想知道是否可以像 bash 中的变量一样保存。我正在编写一个脚本,您可以在其中像农场和矿山一样进行构建,我只是想知道即使在我停止程序然后重新启动之后是否有可能恢复这些变量。所以假设我已经建立了 4 个农场,农场将是农场 = 4,我可以以某种方式把这个变量带回来吗?我知道如何制作一个可以在其上制作高分列表的页面(我是为猜谜游戏做的。),但是我不知道这在 bash 中是否可行。

4

2 回答 2

7

您可以以该格式将所有内容写入文件:

farm=4
myname=gniourf

然后获取该文件:

#!/bin/bash

# Recover the saved states:
source file_where_i_saved_my_stuff

# Now you can recover all your variables!
echo "$farm"
echo "$myname"

编辑

由于您想知道如何保存变量,因此这里有一个快速提示,其中包含许多其他答案中未提供的内容。

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

cat <<EOF > file_where_i_saved_my_stuff
variable1=$variable1
variable2=$variable2
...
variable1000000=$variable1000000
EOF

事实上,出于多种原因,您根本不想这样做。现在,我将解决解决方案:

该方法依赖于这个愚蠢的东西(以及良好的 bash 实践和知识):使用前缀命名您要保存的所有变量,例如,,variable_i_want_to_save_这样您就可以拥有诸如等variable_i_want_to_save_number_of_farms之类的变量variable_i_want_to_save_color_of_granny_dress。不要将此前缀用于您不想保存的变量。

聪明的东西#1

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

"${!prefix@}"

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

因此,在我们的案例中,

for i in "${!variable_i_want_to_save_@}"; do

将遍历以我们美妙的前缀为前缀的所有变量的名称。那不是很棒吗?

聪明的东西#2

如果我处于以下情况:

a=1
b=2
variablename="a"

如何获取名称为变量值的变量的值variablename?简单,使用"${!variablename}"构造。看:

$ a=1
$ b=2
$ variablename=a
$ echo "${!variablename}"
1

${!prefix@}和扩展在 Bash 参考的Shell Parameter Expansion部分中进行了${!variablename}解释(您必须向下滚动一点才能到达那里)。

(破损)解决方案

然后,您可以使用损坏的解决方案将变量保存在文件中,如下所示:

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

这真的很有效也很酷,但是如果你的变量中有空格或任何类型的垃圾字符(可以(并且应该)出现),那么它就会被破坏。哦亲爱的。

解决方案

对你来说,好消息是 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 ?'

你做梦也想不到这么好的东西。或者也许你可以,但请承认它很棒!

因此,您可以在此以绝妙的方式将变量保存在文件中:

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
}

请注意,像这样获取外部文件会导致明显的安全问题,因此请确保仅谨慎使用此方法!

于 2012-12-02T18:55:17.667 回答
5

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

cat<<EOF>/path/to/file
var1="$var1"
var2="$var2"
EOF

并重新创建您以前的环境:

source /path/to/file

或者

. /path/to/file

解释

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

帮助说:

$ LANG=C help source

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.

笔记

如果您出于某些原因想要动态生成具有变量名模式匹配的文件:

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

感谢 gniourf_gniourf 的printf诡计。

于 2012-12-02T18:54:44.997 回答