什么是Python字典的等效,但在Bash中(应该适用于OS X和Linux)。


当前回答

一位同事刚刚提到了这个帖子。我在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和朋友们。

其他回答

下面是一个相当做作但希望有指导意义的哈希/映射/字典/关联数组示例。假设我有一个字符串数组,我想创建一个映射,从每个单词到它在数组中出现的次数。

当然,有很多方法可以使用管道命令来实现这一点,但重点是演示核心的映射操作:使用-v检查键的存在性、添加键-值映射、检索键的值、更新键的现有值以及遍历整个映射以打印键-值对。

#!/usr/bin/bash
set -o pipefail

bash --version | head -1

words=(foo foo bar bar foo baz baz foo bar)
declare -A counter=() # create the map

for word in "${words[@]}"; do
    # if the key doesn't yet exist in the map, add it
    if [[ ! -v counter[$word] ]]; then
        counter[$word]=0
    fi

    # look up the value of a key, add one, and store back in the map
    counter[$word]=$((${counter[$word]} + 1))
done

# iterate the map
for key in "${!counter[@]}"; do
    echo "$key ${counter[$key]}"
done

输出:

GNU bash, version 5.1.16(1)-release (x86_64-pc-linux-gnu)
foo 4
bar 3
baz 2

Bash 3解决方案:

在阅读一些答案的过程中,我整理了一个快速的小函数,我想贡献出来,可能会帮助到其他人。

# Define a hash like this
MYHASH=("firstName:Milan"
        "lastName:Adamovsky")

# Function to get value by key
getHashKey()
 {
  declare -a hash=("${!1}")
  local key
  local lookup=$2

  for key in "${hash[@]}" ; do
   KEY=${key%%:*}
   VALUE=${key#*:}
   if [[ $KEY == $lookup ]]
   then
    echo $VALUE
   fi
  done
 }

# Function to get a list of all keys
getHashKeys()
 {
  declare -a hash=("${!1}")
  local KEY
  local VALUE
  local key
  local lookup=$2

  for key in "${hash[@]}" ; do
   KEY=${key%%:*}
   VALUE=${key#*:}
   keys+="${KEY} "
  done

  echo $keys
 }

# Here we want to get the value of 'lastName'
echo $(getHashKey MYHASH[@] "lastName")


# Here we want to get all keys
echo $(getHashKeys MYHASH[@])
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 3中使用动态变量创建hashmap。我在我的回答中解释了它是如何工作的:Shell脚本中的关联数组

您还可以查看shell_map,它是bash 3中实现的HashMap。