Додайте новий елемент до масиву, не вказуючи індекс у Bash


Відповіді:


1539

Так, є:

ARRAY=()
ARRAY+=('foo')
ARRAY+=('bar')

Довідкове керівництво Bash :

У контексті, коли оператор призначення присвоює значення змінній оболонки або індексу масиву (див. Масиви), оператор '+ =' може використовуватися для додавання або додавання до попереднього значення змінної.


21
Це добре працює з bash 3.2.48 (OS X 10.8.2). Зауважте, що ARRAYце лише заповнювач місця для фактичного імені змінної. Навіть якщо ваші індекси масиву не є послідовними, додавання з +=просто призначить найвищий індекс + 1.
mklement0

3
Чи є щось подібне у версії 4.2.24 (1) bash?
Алі Ісмаїлов

195
Важливо зауважити, що ARRAY + = ('foo') відрізняється від ARRAY + = 'foo', який додає рядок 'foo' до запису з найнижчою (?) Клавішею.
Конструктор

8
За даними wiki.bash-hackers.org/scripting/bashchanges , цей синтаксис вперше з'явився у версії 3.1-alpha1.
Девід Яв

39
@Jas: щоб отримати доступ до всього масиву, ви повинні використовувати ${myarray[@]}- посилання на змінну масиву, як якщо б вона була скалярною - це те саме, що доступ до її елемента 0; іншими словами: $myarrayте саме, що ${myarray[0]}.
mklement0

76

Як зазначає Німий Гай , важливо відзначити, чи починається масив з нуля і є послідовним. Оскільки ви можете виконувати призначення та скасовувати непомітні індекси, ${#array[@]}це не завжди наступний елемент у кінці масиву.

$ array=(a b c d e f g h)
$ array[42]="i"
$ unset array[2]
$ unset array[3]
$ declare -p array     # dump the array so we can see what it contains
declare -a array='([0]="a" [1]="b" [4]="e" [5]="f" [6]="g" [7]="h" [42]="i")'
$ echo ${#array[@]}
7
$ echo ${array[${#array[@]}]}
h

Ось як отримати останній індекс:

$ end=(${!array[@]})   # put all the indices in an array
$ end=${end[@]: -1}    # get the last one
$ echo $end
42

Це ілюструє, як отримати останній елемент масиву. Ви часто бачите таке:

$ echo ${array[${#array[@]} - 1]}
g

Як бачите, оскільки ми маємо справу з розрідженим масивом, це не останній елемент. Це працює як на розріджених, так і на суміжних масивах, хоча:

$ echo ${array[@]: -1}
i

3
Чудові речі; ніколи не знав, що синтаксис підрядок-вилучення може бути застосований і до масивів; правила, визначені методом проб і помилок, є (баш 3.2.48): ${array[@]: start[:count]}Повертає кількість ліків. або, якщо не вказано, всі залишки . починаючи з наступного елема .: - Якщо почати> = 0: з елема. індекс якого = = початок. - Якщо почати <0: з елем. індекс якого (останній індекс масиву + 1) - abs (старт); CAVEAT: якщо abs (start)> (індекс останнього масиву + 1) повертається нульовий рядок. Якщо вказано підрахунок, повертається стільки елементів, навіть якщо їх індекси не є суміжними з самого початку.
mklement0

3
@mklement: У Bash 4.2 ви можете використовувати підписки негативного масиву для доступу до елементів, що рахуються з кінця масиву. ${array[-1]}
Призупинено до подальшого повідомлення.

Це добре знати, дякую. OS X (від 10.8.2) до сих пір використовує 3.2.48 і stackoverflow.com/questions/10418616 / ... каже мені , що, на жаль, «Apple використовувати досить стару версію Bash, так як вони не вантажать код , який ліцензійну під GPL3. "
mklement0

49
$ declare -a arr
$ arr=("a")
$ arr=("${arr[@]}" "new")
$ echo ${arr[@]}
a new
$ arr=("${arr[@]}" "newest")
$ echo ${arr[@]}
a new newest

8
приємно для версій bash, які не підтримують семантику + = оператора, пояснюється e-t172
akostadinov

12
хороше сумісне для назад рішення, але будьте уважні, що якщо в будь-якому з існуючих елементів є пробіли, вони будуть розділені на кілька елементів; використовуйте, arr=("${arr[@]}" "new")якщо у вас є елементи з пробілами в них
kbolino

1
Це також можна використовувати для проштовхування перед масивом, що саме те, що мені потрібно.
Томаш Зато - Відновіть Моніку

29

Якщо ваш масив завжди є послідовним і починається з 0, ви можете зробити це:

array[${#array[@]}]='foo'

# gets the length of the array
${#array_name[@]}

Якщо ви ненавмисно використовуєте пробіли між знаком рівності:

array[${#array[@]}] = 'foo'

Тоді ви отримаєте помилку, схожу на:

array_name[3]: command not found

5
Так, ви можете, але +=синтаксис (див. Відповідь @ e-t172) є (а) простішим, і (b) також працює з масивами, які не є суміжними та / або не починаються з 0.
mklement0,

Чесно кажучи, це рішення (для мене) працює краще, ніж "+ =", тому що з останнім часом довжина іноді неправильна (збільшується на два при додаванні одного елемента) ... тому я віддаю перевагу цій відповіді! :)
Pierpaolo Cira

Це також працює в більш ранніх версіях bash, перед тим, як +=додано, наприклад, версія 2
Zoey Hewll

1
Це також працює, коли у ваших елементів є пробіли - $arr += ($el)здавалося, розділити рядок на пробіл і додати кожен із елементів.
Макс

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.