Основна проблема тут полягає в тому, що розробники bash, які розробляли / реалізували масиви, справді накрутили пух. Вони вирішили, що це ${array}
була просто коротка рука ${array[0]}
, що було поганою помилкою. Особливо, якщо ви вважаєте, що ${array[0]}
не має сенсу, і оцінює порожній рядок, якщо тип масиву є асоціативним.
Призначення масиву приймає форму, у array=(value1 ... valueN)
якій значення має синтаксис [subscript]=string
, тим самим присвоюючи значення безпосередньо певному індексу в масиві. Це робить його таким, що може бути два типи масивів, чисельно індексованих та хеш-індексованих (називаються асоціативними масивами в bash парламенті). Це також робить його таким чином, що ви можете створювати розріджені масиви з індексованим числом. Залишаючи [subscript]=
частину - це коротка рука для числового індексованого масиву, починаючи з порядкового індексу 0 і збільшуючись з кожним новим значенням у виписці про призначення.
Тому ${array}
слід оцінювати весь масив, індекси та всі. Він повинен оцінювати до зворотного твердження про призначення. Будь-який спеціаліст третього курсу повинен це знати. У такому випадку цей код буде працювати саме так, як ви його очікуєте:
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
На жаль, нас відпустив інакше чудова команда розвитку башмаків.
Таким чином, для передачі масиву функції дійсно є лише один варіант, а це використовувати функцію 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[*]}"
а потім записати купу коду всередині функції, щоб зібрати масив.