Основная проблема здесь заключается в том, что разработчик (-и) 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[*]}"
и затем написание кода внутри функции для повторной сборки массива.