bash中的关联数组

时间:2012-10-11 12:07:54

标签: bash shell sed hashtable

我找到了关联数组here的实现,并希望了解代码实际执行的操作。以下是我不理解的代码片段,并希望得到解释。 “

put() {
    if [ "$#" != 3 ]; then exit 1; fi  
    mapName=$1; key=$2; value=`echo $3 | sed -e "s/ /:SP:/g"`  #dont understand 
    eval map="\"\$$mapName\""  **#dont understand** 
    map="`echo "$map" | sed -e "s/--$key=[^ ]*//g"` --$key=$value"  #dont understand 
    eval $mapName="\"$map\""  #dont understand 
}
get() {
    mapName=$1; key=$2

    map=${!mapName}
    #dont understand 
    value="$(echo $map |sed -e "s/.*--${key}=\([^ ]*\).*/\1/" -e 's/:SP:/ /g' )"  
}

getKeySet() {
    if [ "$#" != 1 ]; 
    then 
        exit 1; 
    fi

    mapName=$1; 

    eval map="\"\$$mapName\""

    keySet=`
           echo $map | 
           sed -e "s/=[^ ]*//g" -e "s/\([ ]*\)--/\1/g"   #dont understand 
          ` 
}

感谢。

3 个答案:

答案 0 :(得分:2)

所以首先按照不理解的顺序:

  1. 这只是检查你总是有3个参数的函数,如果提供不同的数字退出1(错误)
  2. 通过将:SP:替换为Hi how are youHi:SP:how:SP:are:SP:you成为{{1}}
  3. 地图存储在var中,其名称为第一个参数提供给put。所以这一行在var中添加了以下文本 - $ key = $ value,这里key是第二个参数,value是转义的第三个参数
  4. 简单地存储值作为第二个参数提供的键的值(第一个是地图的名称)
  5. 要了解更好,请尝试在每次操作后打印您决定用于地图的变量。你很容易看到;) 希望这说清楚。

答案 1 :(得分:1)

我会尝试解释你突出显示的每一行:

    if [ "$#" != 3 ]; then exit 1; fi   #dont understand

如果没有三个参数,则退出并显示错误。

    mapName=$1; key=$2; value=`echo $3 | sed -e "s/ /:SP:/g"`  #dont understand 
  1. 使用第一个参数
  2. 的值设置变量$mapName
  3. 使用第二个参数
  4. 的值设置变量$key
  5. 使用字符串$value替换空格后,将变量:SP:设置为第三个参数的值。

    map="`echo "$map" | sed -e "s/--$key=[^ ]*//g"` --$key=$value"  #dont understand
    
  6. 这将编辑$map变量,删除$key后跟=的第一个出现位置,然后删除非空格字符,然后附加字符串{{ 1}}后跟--的值,然后是$key,最后是=的值。

    $value

    这将评估该行生成的字符串。假设 eval $mapName="\"$map\"" #dont understand $mapNamemyMap$map,则bash将评估的字符串为:

    value

    因此它实际上会设置一个变量,其名称将通过参数传递。

    myMap="value"
    

    这会将变量 map=${!mapName} 的值设置为与$map中的值具有相同名称的变量。示例:假设$mapName$mapName,则a最终会得到$map的内容。

    a

    在这里,我们将 value="$(echo $map |sed -e "s/.*--${key}=\([^ ]*\).*/\1/" -e 's/:SP:/ /g' )" 变量的值设置为$value变量的值,经过几次编辑后:

    1. 仅提取sed表达式中括号内表达式中指定的内容,该表达式匹配不是空格的字符。它之前的文本指定了匹配应该从哪里开始,因此在这种情况下,空格必须在字符串$map之后开始,后跟--变量的值,然后是$key。 `。*'在开始和结束时匹配线的其余部分,并用于之后删除它们。
    2. 恢复空间,即。用实际空格替换=

      :SP:
    3. 这将创建一个值为" $ mapName"的字符串,即。一美元,后跟mapName中包含的字符串,用双引号括起来。在评估时,这将获取名称为eval map="\"\$$mapName\"" 的内容的变量的值。

      希望这有点帮助=)

答案 2 :(得分:0)

Bash,自版本4及更高版本以来,内置了关联数组 要使用它们,您需要使用declare -A

声明一个
#!/usr/bin/env bash

declare -A arr    # 'arr' will be an associative array
                  # now fill it with: arr['key']='value'
arr=(
    [foo]="bar"
    ["nyan"]="cat"
    ["a b"]="c d"
    ["cookie"]="yes please"
    ["$USER"]="$(id "$LOGNAME")"
)

#    -- cmd --                  -- output --
echo "${arr[foo]}"            # bar
echo "${arr["a b"]}"          # c d

user="$USER"
echo "${arr["$user"]}"        # uid=1000(c00kiemon5ter) gid=100...

echo "${arr[cookie]}"         # yes please
echo "${arr[cookies]}"        # <no output - empty value> :(

# keys and values
printf '%s\n' "${arr[@]}"     # print all elements, each on a new line
printf '%s\n' "${!arr[@]}"    # print all keys,     each on a new line

# loop over keys - print <key :: value>
for key in "${!arr[@]}"
do printf '%s :: %s\n' "$key" "${arr["$key"]}"
done

# you can combine those with bash parameter expansions, like
printf '%s\n' "${arr[@]:0:2}" # print only first two elements
echo "${arr[cookie]^^}"       # YES PLEASE