bash



Bash-скрипты: параметры и ключи командной строки


Автор оригинала: Администратор likegeeks.com• Блог компании RUVDS.com,
• Настройка Linux,
• Серверное администрирование
• Перевод
Bash-скрипты: начало
Bash-скрипты, часть 2: циклы
Bash-скрипты, часть 3: параметры и ключи командной строки
Bash-скрипты, часть 4: ввод и вывод
Bash-скрипты, часть 5: сигналы, фоновые задачи, управление сценариями
Bash-скрипты, часть 6: функции и разработка библиотек
Bash-скрипты, часть 7: sed и обработка текстов
Bash-скрипты, часть 8: язык обработки данных awk
Bash-скрипты, часть 9: регулярные выражения
Bash-скрипты, часть 10: практические примеры
Bash-скрипты, часть 11: expect и автоматизация интерактивных утилит

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

$ ./myscript 10 20
В данном примере сценарию передано два параметра — «10» и «20». Всё это хорошо, но как прочесть данные в скрипте?


Чтение параметров командной строки



Оболочка bash назначает специальным переменным, называемым позиционными параметрами, введённые при вызове скрипта параметры командной строки:

• $0 — имя скрипта.

• $1 — первый параметр.

• $2 — второй параметр — и так далее, вплоть до переменной $9, в которую попадает девятый параметр.


Вот как можно использовать параметры командной строки в скрипте с помощью этих переменных:

#!/bin/bash
echo $0
echo $1
echo $2
echo $3
Запустим сценарий с параметрами:

./myscript 5 10 15
Вот что он выведет в консоль.

images/77-1.png
Вывод параметров, с которыми запущен скрипт

Обратите внимание на то, что параметры командной строки разделяются пробелами.

Взглянем на ещё один пример использования параметров. Тут мы найдём сумму чисел, переданных сценарию:

#!/bin/bash
total=$[
$1 + $2 ]
echo The first parameter is $1.
echo The second parameter is $2.
echo The sum is $total.
Запустим скрипт и проверим результат вычислений.

images/77-2.png
Сценарий, который находит сумму переданных ему чисел

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

#!/bin/bash
echo Hello $1, how do you do
Запустим его:

./myscript Adam
Он выведет то, что мы от него ожидаем.

images/77-3.png
Сценарий, работающий со строковым параметром

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

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

${10}

Проверка параметров



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

#!/bin/bash
if [ -n "$1" ]
then
echo Hello $1.
else
echo "No parameters found. "
fi
Вызовем скрипт сначала с параметром, а потом без параметров.

images/77-4.png
Вызов скрипта, проверяющего наличие параметров командной строки


Подсчёт параметров



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

Опробуем её:

#!/bin/bash
echo There were $# parameters passed.
Вызовем сценарий.

./myscript 1 2 3 4 5
В результате скрипт сообщит о том, что ему передано 5 параметров.

images/77-5.png
Подсчёт количества параметров в скрипте

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

#!/bin/bash
echo The last parameter was ${!#}
Вызовем скрипт и посмотрим, что он выведет.

images/77-6.png
Обращение к последнему параметру


Захват всех параметров командной строки



В некоторых случаях нужно захватить все параметры, переданные скрипту. Для этого можно воспользоваться переменными $* и $@. Обе они содержат все параметры командной строки, что делает возможным доступ к тому, что передано сценарию, без использования позиционных параметров.

Переменная $* содержит все параметры, введённые в командной строке, в виде единого «слова».

В переменной $@ параметры разбиты на отдельные «слова». Эти параметры можно перебирать в циклах.

Рассмотрим разницу между этими переменными на примерах. Сначала взглянем на их содержимое:

#!/bin/bash
echo "Using the \$* method: $*"
echo "-----------"
echo "Using the \$@ method: $@"
Вот вывод скрипта.

images/77-7.png
Переменные $* и $@

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

#!/bin/bash
count=1
for param in "$*"
do
echo "\$* Parameter #$count = $param"
count=$((
$count + 1 ))
done
count=1
for param in "$@"
do
echo "\$@ Parameter #$count = $param"
count=$((
$count + 1 ))
done
Взгляните на то, что скрипт вывел в консоль. Разница между переменными вполне очевидна.

images/77-8.png
Разбор переменных $* и $@ в цикле

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


Команда 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, которая сдвигает значения параметров на одну позицию.

images/77-9.png
Использование команды shift для перебора параметров

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


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



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

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

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

#!/bin/bash
echo -n "Enter your name: "
read name
echo "Hello $name, welcome to my program."
Обратите внимание на то, что команда echo, которая выводит приглашение, вызывается с ключом -n. Это приводит к тому, что в конце приглашения не выводится знак перевода строки, что позволяет пользователю скрипта вводить данные там же, где расположено приглашение, а не на следующей строке.

images/77-10.png
Обработка пользовательского ввода

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

#!/bin/bash
read -p "Enter your name: " first last
echo "Your data for $last, $first…"
Вот что выведет скрипт после запуска.

images/77-11.png
Несколько переменных в команде read

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

#!/bin/bash
read -p "Enter your name: "
echo Hello $REPLY, welcome to my program.
images/77-12.png
Использование переменной среды 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, выведя извинения.

images/77-13.png
Ограничение времени на ввод данных


Ввод паролей



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

#!/bin/bash
read -s -p "Enter your password: " pass
echo "Is your password really $pass? "
Вот как отработает этот скрипт.

images/77-14.png
Ввод конфиденциальных данных


Чтение данных из файла



Команда read может, при каждом вызове, читать одну строку текста из файла. Когда в файле больше не останется непрочитанных строк, она просто остановится. Если нужно получить в скрипте всё содержимое файла, можно, с помощью конвейера, передать результаты вызова команды cat для файла, конструкции while, которая содержит команду read (конечно, использование команды cat выглядит примитивно, но наша цель — показать всё максимально просто, ориентируясь на новичков; опытные пользователи, уверены, это поймут).

Напишем скрипт, в котором используется только что описанный подход к чтению файлов.

#!/bin/bash
count=1
cat myfile |
while read line
do
echo "Line $count: $line"
count=$((
$count + 1 ))
done
echo "Finished"
Посмотрим на него в деле.

images/77-15.png
Чтение данных из файла

Тут мы передали в цикл while содержимое файла и перебрали все строки этого файла, выводя номер и содержимое каждой из них.

Потеря истории команд
добавить строки в .bashrc
shopt -s histappend
PROMPT_COMMAND='history -a'

Так история команд будет добавляться к старой, а не перезаписывать ее, и запись будет происходить каждый раз в момент отображения подсказки bash.







Поиск по введенному префиксу.
То есть набираем "cd " и при нажатии вверх-вниз видим только комманды начинающеися с "cd ". По мне это удобнее чем использовать Ctrl+R

Итак открываем на редактирование файл ~/.inputrc и записываем туда

"\e[A": history-search-backward
"\e[B": history-search-forward


Разорванные многострочные команды в истории команд
Добавьте в .bashrc, и многострочные команды будут записываться в одну строку, что облегчит редактирование.
shopt -s cmdhist

Дубликаты в истории команд
Добавьте опять таки к .bashrc.
export HISTCONTROL="ignoredups"

Или даже лучше, добавьте
export HISTIGNORE="&:ls:[bf]g:exit"

Это позволит избавиться от дубликатов, а также от ls, bg, fg и exit, что сделает историю команд bash более читабельной.











Содержание