BASH: использование массивов

By | 11/13/2013
 

terminal

Массив (в некоторых языках программирования также таблица, ряд) — набор однотипных компонентов (элементов), расположенных в памяти непосредственно друг за другом, доступ к которым осуществляется по индексу (индексам). В отличие от списка, массив является структурой с произвольным доступом (Материал из Википедии).

В BASH имеется два вида массивов – Индексированные массивы (indexed arrays) и Ассоциативные массивы (Associative Arrays или hash-массивы). Ассоциативные массивы появились в BASH начиная с версии 4 и, хотя у них больше возможностей по сравнению с  Индексированными массивами, последние до сих пор остаются наиболее используемыми. Тут мы будем рассматривать примеры с индексированными массивами. Для Ассоциативных массивов – позже будет отдельная статья.

Инициализация массивов

Инициализация, или объявление массивов происходит либо явно, с использованием команды declare, либо при указании массива прямо в коде. Обратите внимание на то, что если не использовать команду declare – то массив по-умолчанию будет считаться индексированным.

Примеры объявления массивов:

$ declare -a array
$ array=( [1]=one [2]=two )
$ echo ${array[@]}
one two

Или без использования declare:

$ array2=( [1]=one [2]=two )
$ echo ${array2[@]}
one two

Другие способы инициализации индексированных массивов – без указания непосредственно индексов:

$ array3=(zero one two)
$ echo ${array3[@]}
zero one two

В таком случае индексы начинаются с нуля:

$ echo ${array3[0]}
zero

Ещё одна возможность определения массива:

$ array4[1]=four
$ echo ${array4[1]}
four

Но элемент с индексом [2] будет пустым:

$ echo ${array4[2]}

Индекс элемента массива – это целое положительное число (в случае индексированных массивов) либо “выражение” (string) – в случае ассоциативных массивов, определяющее имя и/или положение элемента массива.

Например, в массиве:

$ array2=( [1]=one [2]=two )

[1] и [2] являются индексами, которые определяют элементы массива – one и two соответственно. В случае индексированных массивов использование индексов не обязательно должно непрерывным. Например:

$ array5=( [1]=one [2]=two [5]=five )
$ echo ${array5[@]}
one two five

В случае использования массивов можно использовать некоторые возможности обычных переменных, например – вывести количество элементов массива:

$ echo ${#array5[@]}
3

Или вывести количество символов в определённом элементе массива:

$ array[3]=four
$ echo ${#array[3]}
4

Удаление элементов массива

Для удаления элемента массива используется та же команда, что и в случае переменных. Например – удалим элемент [2]=two из предыдущего примера:

$ echo ${array5[@]}
one two five
$ unset array5[2]
$ echo ${array5[@]}
one five

Так же можно удалить и все элементы массива:

$ unset array5[@]
$ echo ${array5[@]}

Аналогично удаляется и весь массив целиком:

$ unset array5
$ echo ${array5[@]}

Добавление и удаление элементов массива

Добавить новые элемент в конец массива:

$ array5=( [1]=one [2]=two [5]=five )

$ echo ${array5[@]}
one two five
$ array5+=(six)

$ echo ${array5[@]}
one two five six

В этом примере элемент добавляется последним. Так как выше был объявлен элемент с индексом [5] – то новый будет добавлен с индексом [6]:

$ echo ${array5[6]}
six

Или добавить в определённую позицию:

$ array5+=([3]=six)

$ echo ${array5[@]}
one two six five

Математические операции с элементами массива

Допустимо использование команды expr для выполнения операций над элементами.

Например – инициализировать элемент, который является суммой двух других элементов:

$ intArray=(1 2 3 4 5)
$ echo ${intArray[@]}
1 2 3 4 5

Добавляем новый элемент:

$ intArray[5]=`expr ${intArray[0]} + ${intArray[1]}`
$ echo ${intArray[5]}
3

Или умножение:

$ intArray[6]=`expr ${intArray[1]} * ${intArray[2]}`
$ echo ${intArray[6]}
6

Получение элемента массива

Определим массив:

$ intArray=(1 2 3 4 5)
$ echo ${intArray[@]}
1 2 3 4 5

Получить только первый элемент:

$ echo ${intArray[0]}
1

Или так (получить все элементы начиная с позиции 0, вывести 1 элемент):

$ echo ${intArray[@]:0:1}
1

Получить все элементы, начиная с позиции 3:

$ echo ${intArray[@]:2}
3 4 5

Получить 2 элемента массива, начиная с позиции 3:

$ echo ${intArray[@]:2:2}
3 4

Не забывайте, что если индексы элементов массива не были заданы явно – то они начинаются с 0.

Получить только последний элемент можно так:

$ echo ${intArray[@]:(-1)}
5

Или последние два параметра:

$ echo ${intArray[@]:(-2)}
4 5

Только предпоследний:

$ echo ${intArray[@]:(-2):1}
4

Переменные в массивах

В качестве элементов массива можно использовать обычные переменные.

Например:

$ a=1
$ b=2
$ c=3
$ array=($a $b $c)
$ echo ${array[@]}
1 2 3

Вложенные массивы

В качестве элемента массива можно задавать элемент из уже инициализированного массива.

Например:

$ echo ${array[@]}
1 2 3 four
$ subArray=( [1]=${array[0]} [2]=${array[1]} )

Тут мы создаём новый массив, у которого элемент с индексом [1] получает значение из массива array и его элемента [0], а элемент [2] массива subArray – получает значение элемента [1] массива array:

$ echo ${subArray[@]}
1 2

Другой пример, аналогичный первому:

$ subArray=( [1]=${array[@]:0:1} [2]=${array[@]:1:1} )

Тоже самое:

$ echo ${subArray[@]}
1 2

Наполнение массива

Получить все строки из файла и добавить их элементами массива можно так:

$ cat test.log
Boom
ERROR
ERROR
ERROR
ERROR
Boom
ERROR
Boom
$ unset array
$ array=( `cat "test.log"` )
$ echo ${array[@]}
Boom ERROR ERROR ERROR ERROR Boom ERROR Boom

Или так:

$ array=( $(cat "test.log") )
$ echo ${array[@]}
Boom ERROR ERROR ERROR ERROR Boom ERROR Boom

Другой пример – получить PID всех процессов Java и занести их в массив:

$ unset array
$ array=( `ps aux | grep java | awk '{print $2}'` )
$ echo ${array[@]}
14435 14469 14487 15736 15737 17603 26548 27436

Или так:

$ unset array
$ array=( $(ps aux | grep java | awk '{print $2}') )
$ echo ${array[@]}
14435 14469 14487 15736 15737 17603 26548 27496

Массивы так же можно использовать в циклах, например:

$ for i in "${array[@]}"; do echo "$i"; done
14435
14469
14487
15736
15737
17603
26548
27496

Примеры использования массивов можно найти  в скриптах BASH: функция проверки значения элемента в массиве и LDAP + BASH: скрипт резервного копирования и восстановления базы данных LDAP.

UPD 11.2016 Ещё один пример использования массивов: BASH: массивы, пример – скрипт получения логов из Docker-контейнеров

Ссылки по теме

http://mywiki.wooledge.org
http://www.thegeekstuff.com
http://poplinux.ru
http://www.linuxjournal.com
http://rus-linux.net


  • анон
     

    привет, лишняя единичка в названии массива в первом примере 🙂

  • Никита
     

    Добрый день! Вопрос по разделу “Наполнение массива”. А как быть в варианте наполнения из файла, если в строках содержатся пробелы? В предложенном коде в элемент массива запишется значение до пробела

    • Александр
       

      Для решения этой проблемы можно сделать так:

      OLDIFS=$IFS
      IFS=$’n’
      array1=( `cat “$1″` )
      IFS=$OLDIFS

      В переменной IFS как раз указываются разделители переменных. По умолчанию это пробельные символы, мы же указываем “Разделять переменные по переносу строки”

  • Александр Галушко
     

    Круто. Спасибо. +1 к карме!

  • Anatoly Egorov
     

    Задан символьный массив. Ввести с клавиатуры символ и вывести на консоль количество всех таких символов в массиве.

    № 2. Задание: . Ввести с клавиатуры элементы цифрового массива и еще две цифры. Вывести на консоль сумму порядковых номеров нечетных элементов
    массива, значения которых лежат в диапазоне, определяемом введенными
    цифрами.
    № 3. Задание: Сравнить мощности множеств А и В. Под мощностью множества понимается количество его элементов, не считая повторов.
    № 4 Задание: Удалить из множеств А и В элементы множества С.
    помогите, с чего начать?