Основная причина, по которой ваша вторая попытка не работает, заключается в том, что вы пытаетесь решить другую проблему, используя то же решение.
В первом наборе данных у вас есть два массива с числовыми индексами, в которых ключи не имеют никакого значения, кроме, возможно, порядка, в котором они появляются, и их значения — это то, что действительно имеет значение. Я интерпретировал это как означающее, что вы хотите линейно объединить эти значения в новый массив с новым индексом, который отбрасывает предыдущие ключи, но сохраняет исходный порядок элементов, а также порядок, в котором вы их передали.
Во втором наборе данных у вас есть два ассоциативных индексированных массива, где ключи являются значениями, а значения на самом деле просто заполнители. Я заметил, что вы использовали числовые ключи, которые, если вы решили продолжать использовать массивы с числовыми индексами, позволили бы вам сохранить как порядок значений, так и порядок ключей, при условии, что вы хотите, чтобы ключи были в порядке возрастания...
Итак, для решения этих проблем у меня есть 3 удобные функции, которые я написал, которые используют declare и eval для ускорения объединения/объединения больших массивов, а не с использованием циклов для назначения каждого. Они также принимают переменное количество массивов в качестве аргумента, поэтому вы можете объединять/объединять/сбрасывать сколько угодно из них.
ПРИМЕЧАНИЕ. Я заменил значение/ключ «30» на «30 30», чтобы продемонстрировать, как в некоторых случаях строка будет вести себя иначе, чем число.
join_arrays(){
# <array> [<array> ...] <destination array>
# linear concatenates the values, re-keys the result.
# works best with indexed arrays where order is important but index value is not.
local A_;
while (( $# > 1 )); do
A_+="\"\${$1[@]}\" ";
shift;
done
eval "$1=($A_)";
}
# This works by building and running an array assignment command
# join_array a1 a2 a3 becomes a3=("${a1[@]" "$a2[@]" );
merge_arrays(){
# <array> [<array> ...] <destination array>
# merges the values, preserves the keys.
# works best with assoc arrays or to obtain union-like results.
# if a key exists in more than one array the latter shall prevail.
local A_ B_;
while (( $# > 1 )); do
B_=`declare -p $1`;
B_=${B_#*=??};
A_+=${B_::-2}" ";
shift;
done
eval "$1=($A_)";
}
# this crops the output of declare -p for each array
# then joining them into a single large assignment.
# try putting "echo" in front of the eval to see the result.
dump_arrays(){
# <array> [<array> ...]
# dumps array nodes in bash array subscript assignment format
# handy for use with array assignment operator. Preseves keys.
# output is a join, but if you assign it you obtain a merge.
local B_;
while (( $# > 0 )); do
B_=`declare -p $1`;
B_=${B_#*=??};
printf "%s " "${B_::-2}";
shift;
done
}
# same as above but prints it instead of performing the assignment
# The data sets, first the pair of indexed arrays:
declare -a array1=( 5 10 15 );
declare -a array2=( 20 25 "30 30" );
# then the set of assoc arrays:
declare -a array3=( [5]=true [10]=true [15]=true );
declare -a array4=( [20]=true [25]=true ["30 30"]=true );
# show them:
declare -p array1 array2 array3 array4;
# an indexed array for joins and an assoc array for merges:
declare -a joined;
declare -A merged;
# the common way to join 2 indexed arrays' values:
echo "joining array1+array2 using array expansion/assignment:";
joined=( "${array1[@]}" "${array2[@]}" );
declare -p joined;
объявить -ajoin='([0]="5" [1]="10" [2]="15" [3]="20" [4]="25" [5]="30 30" )'
# this does exactly the same thing, mostly saves me from typos ;-)
echo "joining array1+array2 using join_array():";
join_arrays array1 array2 joined;
declare -p joined;
объявить -ajoin='([0]="5" [1]="10" [2]="15" [3]="20" [4]="25" [5]="30 30" )'
# this merges them by key, which is inapropriate for this data set
# But I've included it for completeness to contrast join/merge operations
echo "merging array1+array2 using merge_array():";
merge_arrays array1 array2 merged;
declare -p merged;
объявить -A merged='([0]="20" [1]="25" [2]="30 30" )'
# Example of joining 2 associative arrays:
# this is the usual way to join arrays but fails because
# the data is in the keys, not the values.
echo "joining array3+array4 using array expansion/assignment:"
joined=( "${array3[@]}" "${array4[@]}" );
declare -p joined;
объявить -ajoin='([0]="true" [1]="true" [2]="true" [3]="true" [4]="true" [5]="true") '
# and again, a join isn't what we want here, just for completeness.
echo "joining array3+array4 using join_array():";
join_arrays array3 array4 joined;
declare -p joined;
объявить -ajoin='([0]="true" [1]="true" [2]="true" [3]="true" [4]="true" [5]="true") '
# NOW a merge is appropriate, because we want the keys!
echo "merging array3+array4 using merge_array():"
merge_arrays array3 array4 merged;
declare -p merged;
объявить -A merged='([25]="true" [20]="true" ["30 30"]="true" [10]="true" [15]="true" [5]=" истинный" )'
# Bonus points - another easy way to merge arrays (assoc or indexed) by key
# Note: this will only work if the keys are numeric...
join_arrays array1 array2 joined;
# error expected because one keys is "30 30" ...
eval joined+=(`dump_arrays merged`);
bash: 30 30: синтаксическая ошибка в выражении (токен ошибки «30»)
declare -p joined
объявить -ajoin='([0]="5" [1]="10" [2]="15" [3]="20" [4]="25" [5]="30 30" [20]="правда" [25]="правда")'
# Note: assoc arrays will not be sorted, even if keys are numeric!
join_arrays array1 array2 joined;
eval merged+=(`dump_arrays joined`);
declare -p merged
объявить -A merged='([25]="true" [20]="true" ["30 30"]="true" [10]="true" [15]="true" [0]=" 5" [1]="10" [2]="15" [3]="20" [4]="25" [5]="true30 30" )'
Последнее примечание: выше вы можете видеть, что ключ [5] имеет значения ключа [5] двух исходных массивов, объединенных, потому что я использовал оператор +=. Если вы просто используете его для слияния списков флагов, это безопасно, но для слияния списков значимых значений с возможными конфликтами клавиш лучше придерживаться функции merge_array().
person
Wil
schedule
20.03.2018
[key]=value
элементов для каждого ключа. Я не знаю такого расширения. Самое близкое, что я могу придумать, это то, что дает вамdeclare -p
(которое вам нужно будет массировать, чтобы использовать). - person Etan Reisner   schedule 22.04.2015