Наши партнеры








Книги по Linux (с отзывами читателей)

Библиотека сайта rus-linux.net

На главную -> MyLDP -> Электронные книги по ОС Linux
Руководство по Bash для начинающих
Назад Глава 10: Подробнее о переменных Вперед

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

Создание массивов

Массив - это переменная, в которой хранится несколько значений. Любая переменная может использоваться как массив. На максимальный размер массива ограничений нет и нет никаких других требований к элементам массива, за исключением лишь того, что элементы массива имеют индексы и значения индексов идут подряд. Массивы начинаются с нулевого элемента: индекс первого элемента равен 0.

Косвенное объявление, задающее переменную, выполняется следующим образом:

ARRAY[INDEXNR]=value 

INDEXNR рассматривается как арифметическое выражение, результат вычисления которого должен быть положительным числом.

Явное объявление массива выполняется с помощью встроенной команды declare:

declare -a ARRAYNAME 

Также допускается объявление с указанием индекса, но индекс будет игнорироваться. С помощью встроенных команд declare и readonly для массива можно определять атрибуты. Атрибуты действуют для всех переменных в массиве, у вас не может быть смешанных массивов.

Массив переменных можно также объявить с помощью инструкции присваивания следующего формата:

ARRAY=(value1 value2 ... valueN) 

Каждое значение value в этом формате имеет вид [номериндекса =]строка. Индекс не является обязательным. Если он указан, то он используется в инструкции присваивания; в противном случае в качестве индекса используется значение индекса, которое уже было назначено, плюс один. Этот формат можно также использовать в команде declare. Если индексы не указываются, индексация начинается с нуля.

Добавление отсутствующих или дополнительных элементов массива осуществляется следующим образом:

ARRAYNAME[indexnumber]=value 

Помните, что во встроенной команде read есть параметр -a, который позволяет читать и назначать значения элементам массива.

Получение доступа к содержимому массива

Чтобы получить доступ к содержимому элемента в массиве, используйте фигурные скобки. Как показано в следующем примере, они необходимы для того, чтобы отключить интерпретацию, выполняемую командной оболочкой, с помощью которой происходит подстановка операторов. Если в качестве номера индекса указывается "@" или "*", то выдаются все элементы массива.

[bob in ~] ARRAY=(one two three)

[bob in ~] echo ${ARRAY[*]}
one two three

[bob in ~] echo $ARRAY[*]
one[*]

[bob in ~] echo ${ARRAY[2]}
three

[bob in ~] ARRAY[3]=four

[bob in ~] echo ${ARRAY[*]}
one two three four

Если переменная массива указывается без указания номера индекса, то в результате будет получено содержимое первого элемента массива, т. е. элемента с нулевым индексом.

Удаление переменных массивов

Для уничтожения массивов или элементов массива используется встроенная команда unset:

[bob in ~] unset ARRAY[1]

[bob in ~] echo ${ARRAY[*]}
one three four

[bob in ~] unset ARRAY

[bob in ~] echo ${ARRAY[*]}
<--no output-->

Примеры массивов

Практические примеры использования массивов найти трудно. Вы легко найдете множество скриптов, которые в вашей системе, в действительности, ничего не делают, но в них используются массивы для вычисления математических рядов. И это будут одни из наиболее интересных примеров ... В большинстве скриптов всего лишь в упрощенном виде показывается, что вы, теоретически, можете делать с массивами.

Причина этого состоит в том, что массивы являются сравнительно сложными структурами. Вы обнаружите, что большинство практических примеров, в которых используются массивы, уже реализованы в вашей системе, но на более низком уровне — на языке программирования C, на котором написаны большинство команд UNIX. Хорошим примером является встроенная команда Bash history. Те читатели, которым это интересно, могут поискать исходный код Bash в директории built-ins и взглянуть на файл fc.def, используемый при компиляции встроенных команд.

Еще одна причина того, что трудно найти хорошие примеры, состоит в том, что массивы поддерживаются не во всех командных оболочках, и из-за них нарушается совместимость.

После многодневного поиска, я, наконец, нашел приведенный ниже пример, работающий у Интернет-провайдера. С помощью этого скрипта распространяются конфигурационные файлы веб сервера Apache по хостам на ферме веб-серверов:

#!/bin/bash

if [ $(whoami) != 'root' ]; then
        echo "Must be root to run $0"
        exit 1;
fi
if [ -z $1 ]; then
        echo "Usage: $0 <path/to/httpd.conf>"
        exit 1
fi

httpd_conf_new=$1
httpd_conf_path="/usr/local/apache/conf"
login=htuser

farm_hosts=(web03 web04 web05 web06 web07)

for i in ${farm_hosts[@]}; do
        su $login -c "scp $httpd_conf_new ${i}:${httpd_conf_path}"
        su $login -c "ssh $i sudo /usr/local/apache/bin/apachectl graceful"

done
exit 0

Первые две проверки выполняются для того, чтобы узнать, сможет ли пользователь, имеющий надлежащие права доступа, запускать скрипт с правильными аргументами. Имена хостов, которые необходимо сконфигурировать, перечислены в массиве farm_hosts. Затем на все эти хосты передается конфигурационный файл Apache, после чего перезапускается демон. Обратите внимание на использование команд из пакета Secure Shell suite, обеспечивающих шифрование соединения с удаленными узлами.

Спасибо Евгению и его коллегам за этот вклад.

Следующий пример представил Дэн Рихтер (Dan Richter). Он столкнулся со следующей проблемой:

"... На сайте моей компании есть демонстрационные примеры, и каждую неделю кто-нибудь должен все их проверять. Поэтому у меня есть задание cron, которое заполняет массив возможными кандидатами; в задании cron для определения недели в году используется команда date +%W и для того, чтобы получить правильный индекс, выполняется операция по модулю. Счастливчик получает уведомление по электронной почте".

И ниже приводится способ ее решения:

#!/bin/bash
# This is get-tester-address.sh 
#
# First, we test whether bash supports arrays.
# (Support for arrays was only added recently.)
#
whotest[0]='test' || (echo 'Failure: arrays not supported in this version of
bash.' && exit 2)
                                                                                
#
# Our list of candidates. (Feel free to add or
# remove candidates.)
#
wholist=(
     'Bob Smith <bob@example.com>'
     'Jane L. Williams <jane@example.com>'
     'Eric S. Raymond <esr@example.com>'
     'Larry Wall <wall@example.com>'
     'Linus Torvalds <linus@example.com>'
   )
#
# Count the number of possible testers.
# (Loop until we find an empty string.)
#
count=0
while [ "x${wholist[count]}" != "x" ]
do
   count=$(( $count + 1 ))
done
                                                                                
#
# Now we calculate whose turn it is.
#
week=`date '+%W'`       # The week of the year (0..53).
week=${week#0}          # Remove possible leading zero.
                                                                                
let "index = $week % $count"   # week modulo count = the lucky person

email=${wholist[index]}     # Get the lucky person's e-mail address.
                                                                                
echo $email             # Output the person's e-mail address.

Затем этот скрипт будет использован в других скриптах, таких как следующий, в котором используется встраиваемый документ (here document):

email=`get-tester-address.sh`   # Find who to e-mail.
hostname=`hostname`             # This machine's name.
                                                                                
#
# Send e-mail to the right person.
#
mail $email -s '[Demo Testing]' <EOF
The lucky tester this week is: $email
                                                                                
Reminder: the list of demos is here:
    http://web.example.com:8080/DemoSites
                                                                                
(This e-mail was generated by $0 on ${hostname}.)
EOF

Предыдущий раздел: Оглавление Следующий раздел:
Типы переменных   Операции над переменными