什么是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
其他回答
一位同事刚刚提到了这个帖子。我在bash中独立实现了哈希表,它不依赖于版本4。我在2010年3月的一篇博客文章(在这里的一些答案之前…)题为bash中的哈希表:
我以前使用cksum来散列,但后来将Java的字符串hashCode转换为本地bash/zsh。
# Here's the hashing function
ht() {
local h=0 i
for (( i=0; i < ${#1}; i++ )); do
let "h=( (h<<5) - h ) + $(printf %d \'${1:$i:1})"
let "h |= h"
done
printf "$h"
}
# Example:
myhash[`ht foo bar`]="a value"
myhash[`ht baz baf`]="b value"
echo ${myhash[`ht baz baf`]} # "b value"
echo ${myhash[@]} # "a value b value" though perhaps reversed
echo ${#myhash[@]} # "2" - there are two values (note, zsh doesn't count right)
它不是双向的,内置的方式要好得多,但无论如何都不应该使用。Bash是用于快速一次性的,这类事情很少涉及可能需要散列的复杂性,除非在~/中。Bashrc和朋友们。
在bash 4之前,在bash中没有使用关联数组的好方法。最好的办法是使用一种真正支持这些功能的解释语言,比如awk。另一方面,bash 4确实支持它们。
至于bash 3中不太好的方法,这里有一个参考:http://mywiki.wooledge.org/BashFAQ/006
我真的很喜欢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()
我同意@lhunath和其他人的观点,关联数组是Bash 4的首选。如果你坚持使用Bash 3 (OSX,你不能更新的旧发行版),你也可以使用expr,它应该无处不在,一个字符串和正则表达式。我喜欢它,尤其是当字典不是太大。
Choose 2 separators that you will not use in keys and values (e.g. ',' and ':' ) Write your map as a string (note the separator ',' also at beginning and end) animals=",moo:cow,woof:dog," Use a regex to extract the values get_animal { echo "$(expr "$animals" : ".*,$1:\([^,]*\),.*")" } Split the string to list the items get_animal_items { arr=$(echo "${animals:1:${#animals}-2}" | tr "," "\n") for i in $arr do value="${i##*:}" key="${i%%:*}" echo "${value} likes to $key" done }
现在你可以使用它:
$ animal = get_animal "moo"
cow
$ get_animal_items
cow likes to moo
dog likes to woof
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