我在处理关联数组时遇到两个问题。第一个是我无法保留自定义订单。
#!/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
有帮助吗?谢谢。
答案 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数组,但是我建议不要使用它们。