【问题标题】:Improving functions to backup and restore a bash dictionary [duplicate]改进备份和恢复 bash 字典的功能 [重复]
【发布时间】:2021-07-19 12:48:14
【问题描述】:

我写了这两个简单的函数来备份和恢复 bash 字典的内容:

declare -A dikv
declare -A dict

backup_dikv()
{
    FILE=$1
    rm -f $FILE

    for k in "${!dikv[@]}"
    do  
        echo "$k,${dikv[$k]}" >> $FILE
    done
}

restore_dict()
{
    FILE=$1
    for i in $(cat $FILE)
    do  
        key=$(echo $i | cut -f 1 -d ",")
        val=$(echo $i | cut -f 2 -d ",")
        dict[$key]=$val
    done
}

# Initial values
dikv=( ["k1"]="v1" ["k2"]="v2" ["k3"]="v3" ["k4"]="v4")

backup_dikv /tmp/backup
restore_dict /tmp/backup

echo "${!dict[@]}"
echo "${dict[@]}"

我的问题:

  1. 如您所见,这两个功能非常有限,因为备份 (dikv) 和恢复 (dict) 字典的名称是硬编码的。我想将字典作为输入 ($2) 参数传递,但我不知道如何在 bash 中将字典作为函数参数传递。

  2. 这种方法是将键和值写入文件,使用字符串格式(“键”,“值”)并解析该字符串格式以恢复字典,这是唯一/最有效的方法吗?您知道备份和恢复字典的更好机制吗?

谢谢!

【问题讨论】:

  • 您不能将数组传递给函数。您可以将数组的名称传递给函数,然后使用${!name} 访问数组。
  • 一种可能的方式是将数组格式化为以后可以使用eval 重新创建它。但是,必须注意键或值中对 shell 具有特殊含义的字符,例如单撇号。也许最安全的方法是将键值对写入文件,方法是用 NUL 字节(我能想到的唯一安全分隔符)将它们分开,然后从这个表示中重新创建它。
  • declare -p dikv supposed 打印一些可以evaled 重新创建数组的东西,但它并不总是能正确处理索引中的奇怪字符。

标签: bash dictionary backup restore


【解决方案1】:

使用declare -p 可靠地序列化变量,无论其类型如何

#!/usr/bin/env bash

if [ -f saved_vars.sh ]; then
  # Restore saved variables
  . saved_vars.sh
else
  # No saved variables, so lets populate them
  declare -A dikv=([foo]="foo bar from dikv" [bar]="bar baz from dikv")
  declare -A dict=([baz]="baz qux from dict" [qux]="qux corge from dict")
fi

# Serialise backup dikv dict into the saved_vars.sh file
declare -p dikv dict >'saved_vars.sh'

printf %s\\n "${!dict[@]}"
printf %s\\n "${dict[@]}"

printf %s\\n "${!dikv[@]}"
printf %s\\n "${dikv[@]}"

【讨论】:

  • 不确定是否理解这一点,我运行您的脚本并始终生成包含以下内容的 saved_vars.sh:declare -A dikv declare -A dict
  • 您确定要运行 bash 而不是其他 shell?
  • $ bash --version GNU bash,版本 5.0.17(1)-release (x86_64-pc-linux-gnu) 版权所有 (C) 2019 Free Software Foundation, Inc. 许可 GPLv3+:GPL de GNU 版本 3 o 后 gnu.org/licenses/gpl.html>
【解决方案2】:

找到了一种将数组传递给函数的方法,使用 local -n 这种方式:

declare -A dikv
declare -A dict

backup_dictionary()
{
    local -n dict_ref=$1
    FILE=/tmp/backup

    for k in "${!dict_ref[@]}"
    do  
        echo "$k,${dict_ref[$k]}" >> $FILE
    done
}

restore_dictionary()
{
    local -n dict_ref=$1
    FILE=/tmp/backup

    for i in $(cat $FILE)
    do  
        key=$(echo $i | cut -f 1 -d ",")
        val=$(echo $i | cut -f 2 -d ",")
        dict_ref[$key]=$val
    done
}

dikv=( ["k1"]="v1" ["k2"]="v2" ["k3"]="v3" ["k4"]="v4")

backup_dictionary dikv
restore_dictionary dict

echo "${!dict[@]}"
echo "${dict[@]}"

仍在努力寻找最方便的方式来备份和恢复内容。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-01-14
    • 2011-07-02
    • 2021-08-14
    • 2014-07-24
    • 2013-12-03
    • 2019-06-30
    • 2014-08-10
    • 1970-01-01
    相关资源
    最近更新 更多