Bash-скрипты, руководство в 11 частях — страница 5 из 19

count=$(( $count + 1 ))

done

count=1

for param in "$@"

do

echo "\$@ Parameter #$count = $param"

count=$(( $count + 1 ))

done

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


Разбор переменных $* и $@ в цикле

Переменная $* содержит все переданные скрипту параметры как единый фрагмент данных, в то время как в переменной $@ они представлены самостоятельными значениями. Какой именно переменной воспользоваться — зависит от того, что именно нужно в конкретном сценарии.

Команда shift


Использовать команду shift в bash-скриптах следует с осторожностью, так как она, в прямом смысле слова, сдвигает значения позиционных параметров.


Когда вы используете эту команду, она, по умолчанию, сдвигает значения позиционных параметров влево. Например, значение переменной $3 становится значением переменной $2, значение $2 переходит в $1, а то, что было до этого в $1, теряется. Обратите внимание на то, что при этом значение переменной $0, содержащей имя скрипта, не меняется.


Воспользовавшись командой shift, рассмотрим ещё один способ перебора переданных скрипту параметров:


#!/bin/bash

count=1

while [ -n "$1" ]

do

echo "Parameter #$count = $1"

count=$(( $count + 1 ))

shift

done

Скрипт задействует цикл while, проверяя длину значения первого параметра. Когда длина станет равна нулю, происходит выход из цикла. После проверки первого параметра и вывода его на экран, вызывается команда shift, которая сдвигает значения параметров на одну позицию.


Использование команды shift для перебора параметров

Используя команду shift, помните о том, что при каждом её вызове значение переменной $1 безвозвратно теряется.

Ключи командной строки


Ключи командной строки обычно выглядят как буквы, перед которыми ставится тире. Они служат для управления сценариями. Рассмотрим такой пример:


#!/bin/bash

echo

while [ -n "$1" ]

do

case "$1" in

-a) echo "Found the -a option" ;;

-b) echo "Found the -b option" ;;

-c) echo "Found the -c option" ;;

*) echo "$1 is not an option" ;;

esac

shift

done

Запустим скрипт:


$ ./myscript –a –b –c –d

И проанализируем то, что он выведет в терминал.


Обработка ключей в скрипте

В этом коде использована конструкция case, которая сверяет переданный ей ключ со списком обрабатываемых скриптом ключей. Если переданное значение нашлось в этом списке, выполняется соответствующая ветвь кода. Если при вызове скрипта будет использован любой ключ, обработка которого не предусмотрена, будет исполнена ветвь «*».

Как различать ключи и параметры


Часто при написании bash-скриптов возникает ситуация, когда надо использовать и параметры командной строки, и ключи. Стандартный способ это сделать заключается в применении специальной последовательности символов, которая сообщает скрипту о том, когда заканчиваются ключи и начинаются обычные параметры.


Эта последовательность — двойное тире (--). Оболочка использует её для указания позиции, на которой заканчивается список ключей. После того, как скрипт обнаружит признак окончания ключей, то, что осталось, можно, не опасаясь ошибок, обрабатывать как параметры, а не как ключи. Рассмотрим пример:


#!/bin/bash

while [ -n "$1" ]

do

case "$1" in

-a) echo "Found the -a option" ;;

-b) echo "Found the -b option";;

-c) echo "Found the -c option" ;;

--) shift

break ;;

*) echo "$1 is not an option";;

esac

shift

done

count=1

for param in $@

do

echo "Parameter #$count: $param"

count=$(( $count + 1 ))

done

Этот сценарий использует команду break для прерывания цикла while при обнаружении в строке двойного тире.


Вот что получится после его вызова.


Обработка ключей и параметров командной строки

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

Обработка ключей со значениями


По мере усложнения ваших скриптов, вы столкнётесь с ситуациями, когда обычных ключей уже недостаточно, а значит, нужно будет использовать ключи с некими значениями. Например, вызов сценария в котором используется подобная возможность, выглядит так:


./myscript -a test1 -b -c test2

Скрипт должен уметь определять, когда вместе с ключами командной строки используются дополнительные параметры:


#!/bin/bash

while [ -n "$1" ]

do

case "$1" in

-a) echo "Found the -a option";;

-b) param="$2"

echo "Found the -b option, with parameter value $param"

shift ;;

-c) echo "Found the -c option";;

--) shift

break ;;

*) echo "$1 is not an option";;

esac

shift

done

count=1

for param in "$@"

do

echo "Parameter #$count: $param"

count=$(( $count + 1 ))

done

Вызовем этот скрипт в таком виде:


./myscript -a -b test1 -d

Посмотрим на результаты его работы.


Обработка параметров ключей

В данном примере в конструкции case обрабатываются три ключа. Ключ -b требует наличия дополнительного параметра. Так как обрабатываемый ключ находится в переменной $1, соответствующий ему параметр будет находиться в $2 (тут используется команда shift, поэтому, по мере обработки, всё, что передано сценарию, сдвигается влево). Когда с этим мы разобрались, осталось лишь извлечь значение переменной $2 и у нас будет параметр нужного ключа. Конечно, тут понадобится ещё одна команда shift для того, чтобы следующий ключ попал в $1.

Использование стандартных ключей


При написании bash-скриптов вы можете выбирать любые буквы для ключей командной строки и произвольно задавать реакцию скрипта на эти ключи. Однако, в мире Linux значения некоторых ключей стали чем-то вроде стандарта, которого полезно придерживаться. Вот список этих ключей:


-a Вывести все объекты.

-c Произвести подсчёт.

-d Указать директорию.

-e Развернуть объект.

-f Указать файл, из которого нужно прочитать данные.

-h Вывести справку по команде.

-i Игнорировать регистр символов.

-l Выполнить полноформатный вывод данных.

-n Использовать неинтерактивный (пакетный) режим.

-o Позволяет указать файл, в который нужно перенаправить вывод.

-q Выполнить скрипт в quiet-режиме.

-r Обрабатывать папки и файлы рекурсивно.

-s Выполнить скрипт в silent-режиме.

-v Выполнить многословный вывод.

-x Исключить объект.

-y Ответить «yes» на все вопросы.


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

Получение данных от пользователя


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


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


Эта команда позволяет принимать введённые данные либо со стандартного ввода (с клавиатуры), либо используя другие дескрипторы файлов. После получения данных, эта команда помещает их в переменную:


#!/bin/bash

echo -n "Enter your name: "

read name

echo "Hello $name, welcome to my program."

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


Обработка пользовательского ввода

При вызове read можно указывать и несколько переменных:


#!/bin/bash

read -p "Enter your name: " first last

echo "Your data for $last, $first…"

Вот что выведет скрипт после запуска.


Несколько переменных в команде read

Если, вызвав read, не указывать переменную, данные, введённые пользователем, будут помещены в специальную переменную среды REPLY:


#!/bin/bash

read -p "Enter your name: "

echo Hello $REPLY, welcome to my program.

Использование переменной среды REPLY

Если скрипт должен продолжать выполнение независимо от того, введёт пользователь какие-то данные или нет, вызывая команду read можно воспользоваться ключом -t. А именно, параметр ключа задаёт время ожидания ввода в секундах:


#!/bin/bash

if read -t 5 -p "Enter your name: " name

then

echo "Hello $name, welcome to my script"

else

echo "Sorry, too slow! "

fi

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


Ограничение времени на ввод данных

Ввод паролей


Иногда то, что вводит пользователь в ответ на вопрос скрипта, лучше на экране не показывать. Например, так обычно делают, запрашивая пароли. Ключ -s команды read предотвращает отображение на экране данных, вводимых с клавиатуры. На самом деле, данные выводятся, но команда read делает цвет текста таким же, как цвет фона.


#!/bin/bash

read -s -p "Enter your password: " pass

echo "Is your password really $pass? "