重击关联数组迭代(有序且无重复)

时间:2018-12-12 10:23:59

标签: bash sorting duplicates associative-array

我在处理关联数组时遇到两个问题。第一个是我无法保留自定义订单。

#!/bin/bash

#First part, I just want to print it ordered in the custom created order (non-alphabetical)
declare -gA array
array["PREFIX_THIS","value"]="true"
array["PREFIX_IS","value"]="false"
array["PREFIX_AN","value"]="true"
array["PREFIX_ORDERED","value"]="true"
array["PREFIX_ARRAY","value"]="true"

for item in "${!array[@]}"; do
    echo "${item}"
done

所需的输出是:

PREFIX_THIS,value
PREFIX_IS,value
PREFIX_AN,value
PREFIX_ORDERED,value
PREFIX_ARRAY,value

但是我正在得到这个:

PREFIX_IS,value
PREFIX_ORDERED,value
PREFIX_THIS,value
PREFIX_AN,value
PREFIX_ARRAY,value

直到这里第一个问题。对于第二个问题,顺序并不重要。我向关联数组添加了更多东西,我只想在它上面循环而不重复。添加此内容:

array["PREFIX_THIS","text"]="Text for the var"
array["PREFIX_IS","text"]="Another text"
array["PREFIX_AN","text"]="Text doesn't really matter"
array["PREFIX_ORDERED","text"]="Whatever"
array["PREFIX_ARRAY","text"]="More text"

我只想遍历“ PREFIX_THIS”,“ PREFIX_IS”,“ PREFIX_AN”等,所以每一个仅打印一次。我只想打印循环执行的“ echo”(此部分的顺序并不重要,只打印一次即可)。所需的输出:

PREFIX_ORDERED
PREFIX_AN
PREFIX_ARRAY
PREFIX_IS
PREFIX_THIS

我做到了“肮脏”的事情。但是必须有一种更优雅的方法。这是我的工作方式,但不太优雅:

already_set=""
var_name=""
for item in "${!array[@]}"; do
    var_name="${item%,*}"
    if [[ ! ${already_set} =~ "${var_name}" ]]; then
        echo "${var_name}"
        already_set+="${item}"
    fi
done

有帮助吗?谢谢。

1 个答案:

答案 0 :(得分:1)

迭代顺序

正如Inian在评论中指出的那样,您无法确定"${!array[@]}"扩展关联数组的顺序。但是,您可以将所有键存储在可以手动订购的普通阵列中。

keysInCustomOrder=(PREFIX_{THIS,IS,AN,ORDERED,ARRAY})
for key in "${keysInCustomOrder[@]}"; do
    echo "do something with ${array[$key,value]}"
done

密钥的唯一前缀

对于第二个问题:a["key1","key2"]a["key1,key2"]相同。在bash中,数组始终是一维的,因此没有完美的解决方案。但是,只要,从来都不是key1的一部分,就可以使用以下单线。

$ declare -A array=([a,1]=x [a,2]=y [b,1]=z [c,1]=u [c,2]=v)
$ printf %s\\n "${!array[@]}" | cut -d, -f1 | sort -u
a
b
c

当您的键还可能包含换行符时,请使用空\0将每个键删除。

printf %s\\0 "${!array[@]}" | cut -zd, -f1 | sort -zu

或者,您可以使用参考变量来模拟2D数组,但是我建议不要使用它们。