将由空格分隔的线分割为关联数组

时间:2019-12-13 03:49:02

标签: linux bash shell dictionary awk

如果我的变量数据如下:

Audit 9201 Management 9202 Inventory 9203 Source 9204 Flemingo 9205

我正在尝试将$ var转换为预期的关联数组,如下所示。

var="Audit 9201 Management 9202 Inventory 9203 Source 9204 Flemingo 9205"
declare -A varMap
$ varMap[Audit]=9201
$ varMap[Management]=9202
$ varMap[Inventory]=9203
$ varMap[Source]=9204
$ varMap[Flemingo]=9205

有什么有效的方法可以将上面的$ var变量转换为一个关联数组,以便我可以根据其余代码中的键执行查找?

4 个答案:

答案 0 :(得分:2)

能否请您尝试以下。这将创建动态的自动化脚本,该脚本将具有自动化的数组创建功能,并且还将打印其键和值。 (这些是OP自己在后期提供的测试样本)

var="Audit 9201 Management 9202 Inventory 9203 Source 9204 Flemingo 9205"
echo "$var" | 
awk -v s1="\"" -v array_name="arrvar" '
BEGIN{
  print "declare -A " array_name
}
{
  for(i=1;i<=NF;i+=2){
    print array_name "["$i"]="$(i+1)
  }
}
END{
  print "echo keys, values here for array.." ORS \
  "for key in " s1 "${!"array_name"[@]}" s1 "; do echo " s1 "$key => ${"array_name"[$key]}" s1 "; done"
}
' > file.ksh;chmod 755 file.ksh;./file.ksh

以下命令将创建以下shell脚本:

cat file.ksh
declare -A arrvar
arrvar[Audit]=9201
arrvar[Management]=9202
arrvar[Inventory]=9203
arrvar[Source]=9204
arrvar[Flemingo]=9205
echo keys, values here for array..
for key in "${!arrvar[@]}"; do echo "$key => ${arrvar[$key]}"; done

当我们运行脚本时,它将给出以下输出:

keys, values here for array..
Audit => 9201
Flemingo => 9205
Management => 9202
Source => 9204
Inventory => 9203

逻辑解释:

  • 创建/定义shell变量(在本例中为var)。
  • 我们可以提供名为(在此示例中为vararr)的数组。
  • 这将创建一个名为file.ksh的脚本,您可以根据需要对其进行更改。
  • awk代码正在做什么,它正在读取var(shell变量),然后读取其打印命令来创建由您提供的命名数组。它还正在打印该数组的键和值。注意:它只编写命令来执行此操作,直到现在还不执行它们。
  • 它将输出保存到名为file.ksh的脚本文件中(您可以保留所需的任何名称)。
  • 现在已授予file.ksh权限并运行它,这实际上将创建一个由您提供的名为的数组,并且还会打印带有索引的值。

答案 1 :(得分:2)

while test "$var"; do
    read -r key value var <<<"$var"
    varMap[$key]=$value
done

答案 2 :(得分:1)

像这样,简单,易读且有效:)

# declare a simple string
var='Audit 9201 Management 9202 Inventory 9203 Source 9204 Flemingo 9205'

# declare a simple array, using word spliting
arr=( $var )

# declare an associative array
declare -A varmap

# iterating over array to feed varmap associative array
for ((i=0; i<${#arr[@]}; i+=2)) {
    varmap[${arr[i]}]=${arr[i+1]}
}  

# new request from comments: the max value with key ending with `Management` :
for i in ${!varmap[@]}; do
    if [[ $i == *Management ]]; then
        if ((varmap[$i] > max)); then
            max=${varmap[$i]}
            var=$i
        fi
    fi
done

# test of one of a key
echo ${varmap[Management]}

输出

9202

答案 3 :(得分:1)

请尝试以下方法:

var="Audit 9201 Management 9202 Inventory 9203 Source 9204 Flemingo 9205"
declare -A varMap="($(sed 's/\([^[:blank:]]\+\)[[:blank:]]\+\([^[:blank:]]\+\)/\[\1]=\2/g' <<< "$var"))"

# test
for i in "${!varMap[@]}"; do
    echo "$i => ${varMap[$i]}"
done

结果:

Audit => 9201
Flemingo => 9205
Management => 9202
Source => 9204
Inventory => 9203