Основная проблема здесь заключается в том, что разработчик (-и) bash, спроектировавший / реализовавший массивы, действительно испортил собаку. Они решили, что ${array}это всего лишь короткая рука ${array[0]}, что было плохой ошибкой. Особенно, если учесть, что ${array[0]}это не имеет смысла и вычисляет пустую строку, если тип массива является ассоциативным.
Присвоение массива принимает форму, в array=(value1 ... valueN)которой значение имеет синтаксис [subscript]=string, тем самым присваивая значение непосредственно определенному индексу в массиве. Это позволяет создавать два типа массивов: с числовым индексированием и с хэш-индексированием (называемые ассоциативными массивами на языке bash). Это также позволяет создавать разреженные числовые индексы. [subscript]=Сокращение от части является сокращением для численно индексированного массива, начиная с порядкового индекса 0 и увеличивая с каждым новым значением в операторе присваивания.
Поэтому ${array}следует оценивать весь массив, индексы и все. Следует оценить обратное значение оператора присваивания. Любой третий год CS должен знать это. В этом случае этот код будет работать точно так, как вы ожидаете:
declare -A foo bar
foo=${bar}
Затем передача массивов по значению функциям и присвоение одного массива другому будет работать так, как диктует остальная часть синтаксиса оболочки. Но поскольку они не сделали этого правильно, оператор присваивания =не работает для массивов, и массивы нельзя передавать по значению в функции или в подоболочки или выводить вообще ( echo ${array}) без кода, который можно было бы просмотреть через все это.
Итак, если бы все было сделано правильно, то следующий пример показал бы, как полезность массивов в bash может быть существенно лучше:
simple=(first=one second=2 third=3)
echo ${simple}
результирующий вывод должен быть:
(first=one second=2 third=3)
Затем массивы могут использовать оператор присваивания и передаваться по значению функциям и даже другим сценариям оболочки. Легко сохраняется путем вывода в файл и легко загружается из файла в сценарий.
declare -A foo
read foo <file
Увы, мы были подведены превосходной командой разработчиков bash.
Таким образом, для передачи массива в функцию, на самом деле есть только одна опция, а именно использование функции nameref:
function funky() {
local -n ARR
ARR=$1
echo "indexes: ${!ARR[@]}"
echo "values: ${ARR[@]}"
}
declare -A HASH
HASH=([foo]=bar [zoom]=fast)
funky HASH # notice that I'm just passing the word 'HASH' to the function
приведет к следующему выводу:
indexes: foo zoom
values: bar fast
Поскольку это происходит по ссылке, вы также можете назначить массив в функции. Да, указанный массив должен иметь глобальную область видимости, но это не должно быть слишком сложным, учитывая, что это сценарий оболочки. Для передачи ассоциативного или разреженного индексированного массива по значению в функцию требуется бросить все индексы и значения в список аргументов (не слишком полезный, если это большой массив) в виде одной строки:
funky "${!array[*]}" "${array[*]}"
а затем написать кучу кода внутри функции, чтобы собрать массив.