Bash。关联数组迭代(有序且无重复)
Bash. Associative array iteration (ordered and without duplicates)
我在处理关联数组时遇到两个问题。第一个是我不能在上面保留自定义订单。
#!/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
我做到了 "dirty"。但必须有更优雅的方式。这是我的工作但不是太优雅的方法:
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
有什么帮助吗?谢谢。
迭代顺序
正如 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
当您的键也可能包含换行符时,将每个键删除为 null [=18=]
。
printf %s\0 "${!array[@]}" | cut -zd, -f1 | sort -zu
或者,您可以使用参考变量来模拟二维数组,但我建议不要使用它们。
我在处理关联数组时遇到两个问题。第一个是我不能在上面保留自定义订单。
#!/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
我做到了 "dirty"。但必须有更优雅的方式。这是我的工作但不是太优雅的方法:
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
有什么帮助吗?谢谢。
迭代顺序
正如 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
当您的键也可能包含换行符时,将每个键删除为 null [=18=]
。
printf %s\0 "${!array[@]}" | cut -zd, -f1 | sort -zu
或者,您可以使用参考变量来模拟二维数组,但我建议不要使用它们。