什么是Python字典的等效,但在Bash中(应该适用于OS X和Linux)。
当前回答
hput () {
eval hash"$1"='$2'
}
hget () {
eval echo '${hash'"$1"'#hash}'
}
hput France Paris
hput Netherlands Amsterdam
hput Spain Madrid
echo `hget France` and `hget Netherlands` and `hget Spain`
$ sh hash.sh
Paris and Amsterdam and Madrid
其他回答
只使用文件系统:文件系统是一个树结构,可以用作散列映射。 您的哈希表将是一个临时目录,键将是文件名,值将是文件内容。它的优点是可以处理巨大的hashmap,并且不需要特定的shell。
哈希表创建
hashtable = $ (mktemp - d)
添加一个元素
Echo $value > "$hashtable/$key"
读取一个元素
价值= $ (< hashtable美元- key美元”)
性能
当然,它很慢,但也没那么慢。 我在我的机器上测试了它,使用SSD和btrfs,它每秒可以读/写大约3000个元素。
Bash 4
Bash 4本身支持这个特性。确保脚本的hashbang是#!/usr/bin/env bash或#!/bin/bash,这样你就不会使用sh。确保你要么直接执行你的脚本,要么用bash脚本执行脚本。(没有实际使用Bash执行Bash脚本的情况确实会发生,这将非常令人困惑!)
你可以这样声明一个关联数组:
declare -A animals
可以使用普通数组赋值操作符将其填充为元素。例如,如果你想要一个animal[sound(key)] = animal(value)的映射:
animals=( ["moo"]="cow" ["woof"]="dog")
或者在一行中声明和实例化:
declare -A animals=( ["moo"]="cow" ["woof"]="dog")
然后像普通数组一样使用它们。使用
Animals ['key']='value'设置值 ${animals[@]}展开值 “$ {!animals[@]}”(注意!)来展开键
别忘了引用他们的话:
echo "${animals[moo]}"
for sound in "${!animals[@]}"; do echo "$sound - ${animals[$sound]}"; done
Bash 3
在bash 4之前,没有关联数组。不要使用eval来模拟它们。像避免瘟疫一样避免eval,因为它是shell脚本的瘟疫。最重要的原因是eval将数据视为可执行代码(还有许多其他原因)。
首先也是最重要的:考虑升级到bash 4。这将使整个过程对你来说容易得多。
如果有不能升级的原因,声明是一个更安全的选择。它不像bash代码那样像eval那样计算数据,因此不允许如此容易地进行任意代码注入。
让我们通过介绍概念来准备答案:
首先,间接。
$ animals_moo=cow; sound=moo; i="animals_$sound"; echo "${!i}"
cow
其次,声明:
$ sound=moo; animal=cow; declare "animals_$sound=$animal"; echo "$animals_moo"
cow
把它们放在一起:
# Set a value:
declare "array_$index=$value"
# Get a value:
arrayGet() {
local array=$1 index=$2
local i="${array}_$index"
printf '%s' "${!i}"
}
让我们使用它:
$ sound=moo
$ animal=cow
$ declare "animals_$sound=$animal"
$ arrayGet animals "$sound"
cow
注意:declare不能放在函数中。在bash函数中使用declare将其创建的变量转换为该函数范围内的局部变量,这意味着我们不能使用它访问或修改全局数组。(在bash 4中,您可以使用declare -g来声明全局变量——但在bash 4中,您可以首先使用关联数组,从而避免这种变通方法。)
简介:
升级到bash 4并对关联数组使用declare -A。 如果不能升级,请使用声明选项。 可以考虑使用awk,并完全避免这个问题。
我在bash 3中使用动态变量创建hashmap。我在我的回答中解释了它是如何工作的:Shell脚本中的关联数组
您还可以查看shell_map,它是bash 3中实现的HashMap。
我真的很喜欢Al P的答案,但想要唯一性强制廉价,所以我更进一步-使用目录。有一些明显的限制(目录文件限制,无效的文件名),但它应该适用于大多数情况。
hinit() {
rm -rf /tmp/hashmap.$1
mkdir -p /tmp/hashmap.$1
}
hput() {
printf "$3" > /tmp/hashmap.$1/$2
}
hget() {
cat /tmp/hashmap.$1/$2
}
hkeys() {
ls -1 /tmp/hashmap.$1
}
hdestroy() {
rm -rf /tmp/hashmap.$1
}
hinit ids
for (( i = 0; i < 10000; i++ )); do
hput ids "key$i" "value$i"
done
for (( i = 0; i < 10000; i++ )); do
printf '%s\n' $(hget ids "key$i") > /dev/null
done
hdestroy ids
在我的测试中,它的表现也稍微好一点。
$ time bash hash.sh
real 0m46.500s
user 0m16.767s
sys 0m51.473s
$ time bash dirhash.sh
real 0m35.875s
user 0m8.002s
sys 0m24.666s
我只是想帮帮忙。干杯!
编辑:添加hdestroy()
这里有参数替换,尽管它也可能是非pc的…喜欢间接。
#!/bin/bash
# Array pretending to be a Pythonic dictionary
ARRAY=( "cow:moo"
"dinosaur:roar"
"bird:chirp"
"bash:rock" )
for animal in "${ARRAY[@]}" ; do
KEY="${animal%%:*}"
VALUE="${animal##*:}"
printf "%s likes to %s.\n" "$KEY" "$VALUE"
done
printf "%s is an extinct animal which likes to %s\n" "${ARRAY[1]%%:*}" "${ARRAY[1]##*:}"
BASH 4方式当然更好,但如果你需要一个hack…只有黑客才行。 您可以使用类似的技术搜索数组/散列。