15

相关但不重复:如何在 Bash 中定义哈希表?

我可以定义和使用 bash 哈希,但我无法导出它,即使使用 -x 标志也是如此。例如,以下用于导出(和测试导出)普通字符串变量的方法:

aschirma@graphics9-lnx:/$ export animal_cow="moo"
aschirma@graphics9-lnx:/$ bash -c "echo \$animal_cow"
moo
aschirma@graphics9-lnx:/$ 

但是,如果我尝试导出哈希:

aschirma@graphics9-lnx:/$ declare -A -x animals
aschirma@graphics9-lnx:/$ animals[duck]="quack"
aschirma@graphics9-lnx:/$ echo ${animals[duck]}
quack
aschirma@graphics9-lnx:/$ bash -c "echo \${animals[duck]}"

aschirma@graphics9-lnx:/$ 

似乎嵌套的 bash shell 在其范围内没有散列。我也通过手动输入嵌套的 bash shell 并尝试以交互方式使用哈希来验证这一点。

4

3 回答 3

7

将数组变量编码到环境中并没有真正的好方法。http://www.mail-archive.com/bug-bash@gnu.org/msg01774.html(Chet Ramey 是 bash 的维护者)

于 2012-10-17T23:09:53.080 回答
5

作为这种苛刻的 Bash 限制的解决方法,我正在使用“序列化到临时文件”方法。您可以导出普通变量,因此您可以通过文件路径传递一个数组(关联)。当然,这有局限性,但有时有效并且足够好。

declare -A MAP # export associative array                                                                           
MAP[bar]="baz"                                                                        
declare -x serialized_array=$(mktemp) # create temporary variable 
# declare -p can be used to dump the definition 
# of a variable as shell code ready to be interpreted                                       
declare -p MAP > "${serialized_array}" # serialize an array in temporary file 

# perform cleanup after finishing script                                      
cleanup() {                                                                   
  rm "${serialized_array}"                                                    
}                                                                             
trap cleanup EXIT   

# ... in place where you need this variable ...
source "${serialized_array}" # deserialize an array                         
echo "map: ${MAP[@]}" 
于 2019-03-23T18:23:04.777 回答
0

这有点旧,但无论如何我都会回答,你可以使用临时文件。如果你做对了,你可以包装它来像数组一样使用它们。例如使用此功能:

var() { #  set var or add comtent
    case $1 in 
    *=|*=*) 
        local __var_part1=$( echo "$1" | sed -e 's/=.*//' -e 's/[+,-]//' ) # cut +=/=
        local __var_part2=$( echo "$1" | sed -e 's/.*.=//' )
        local __var12=$tmp_dir/$__var_part1
        mkdir -p ${__var12%/*} #create all subdirs if its an array
        case $1 in 
        *+=*)
                # if its an array try to add new item
            if [ -d $tmp_dir/$__var_part1 ] ; then
            printf  -- $__var_part2 > $tmp_dir/$__var_part1/\  $(( 
                $( echo $tmp_dir/$__var_part2/* \
                    | tail  | basename )\ + 1 ))
            else
            printf -- "$__var_part2" >> $tmp_dir/$__var_part1  
            fi
            ;;
        *-=*) false ;;
            # else just add content
            *)  printf  -- "$__var_part2" > $tmp_dir/$__var_part1 ;;
        esac
        ;;  
    *) # just print var
        if [ -d $tmp_dir/$1 ] ; then
        ls $tmp_dir/$1
        elif [ -e $tmp_dir/$1 ] ; then 
        cat $tmp_dir/$1
        else
        return 1
        fi
        ;;
    esac    
}

# you can use mostly like you set vars in bash/shell
var test='Hello Welt!'
# if you need arrays set it like this:
var fruits/0='Apple'
var fruits/1='Banana'

# or if you need a dict:
var contacts/1/name="Max"
var contacts/1/surname="Musterman"

这不是最快的方法,但它非常灵活、简单并且几乎适用于所有 shell。

于 2013-06-18T20:06:09.953 回答