Руководство по Bash для начинающих | ||
---|---|---|
Назад | Глава 7: Условные инструкции | Вперед |
Иногда вам необходимо указать различные варианты действий, которые должен выполнять скрипт в случае успешного или неудачного выполнения команд. Инструкция if позволяет указывать такие условия.
Самый компактный синтаксис команды if следующий:
if TEST-COMMANDS; then CONSEQUENT-COMMANDS; fi
Выполняется список команд TEST-COMMAND и если они вернут код возврата, равный нулю, будет выполняться список команд CONSEQUENT-COMMANDS. Кодом возврата является код возврата последней выполненной команды, либо ноль, если нет условия, проверяемого на значение истина.
В TEST-COMMAND часто присутствуют сравнения чисел или строк, но также может использоваться любая команда, которая возвращает нулевой код возврата в случае успеха, либо некоторый другой код в случае неудачи. Для проверки состояния файла часто используются унарные выражения. Если аргумент FILE одного из первичных выражений имеет вид /dev/fd/N, то проверяется дескриптор файла "N". При выполнении проверок можно также использовать stdin, stdout и stderr и дескрипторы, соответствующие эти файлам.
В таблице, приведенной ниже, перечисляются так называемые "первичные выражения", из которых состоит команда или список команд TEST-COMMAND. Эти первичные выражения помещаются внутрь квадратных скобок, которые обозначают проверку в условном выражении.
Таблица 7.1. Первичные выражения
Первичное выражение | Значение |
[ -a FILE ] | Истина, если FILE существует. |
[ -b FILE ] | Истина, если FILE существует и является блочным файлом. |
[ -c FILE ] | Истина, если FILE существует и является строковым файлом. |
[ -d FILE ] | Истина, если FILE существует и является директорием. |
[ -e FILE ] | Истина, если FILE существует. |
[ -f FILE ] | Истина, если FILE существует и является обычным файлом. |
[ -g FILE ] | Истина, если FILE существует и у него установлен бит SGID. |
[ -h FILE ] | Истина, если FILE существует и является символической ссылкой. |
[ -k FILE ] | Истина, если FILE существует и у него установлен промежуточный бит округления. |
[ -p FILE ] | Истина, если FILE существует и является именованным конвейером (FIFO). |
[ -r FILE ] | Истина, если FILE существует и доступен для чтения. |
[ -s FILE ] | Истина, если FILE существует и его размер больше нуля. |
[ -t FD ] | Истина, если дескриптор файла FD открыт и ссылается на терминал. |
[ -u FILE ] | Истина, если FILE существует и у него установлен бит SUID (установлен идентификатор пользователя ID) |
[ -w FILE ] | Истина, если FILE существует и доступен для записи. |
[ -x FILE ] | Истина, если FILE существует и является исполняемым. |
[ -O FILE ] | Истина, если FILE существует и его владельцем является действующий пользователь. |
[ -G FILE ] | Истина, если FILE существует и его владелец принадлежит к действующей группе. |
[ -L FILE ] | Истина, если FILE существует и является символической ссылкой. |
[ -N FILE ] | Истина, если FILE существует и был модифицирован после последнего чтения. |
[ -S FILE ] | Истина, если FILE существует и является сокетом. |
[ FILE1 -nt FILE2 ] | Истина, если FILE1 был изменен раньше, чем FILE2, либо если FILE1 существует, а FILE2 не существует. |
[ FILE1 -ot FILE2 ] | Истина, если FILE1 изменен позже, чем FILE2, либо если FILE2 существует, а FILE1 не существует. |
[ FILE1 -ef FILE2 ] | Истина, если FILE1 и FILE2 ссылаются на одно и то же устройство или на одинаковые номера инодов. |
[ -o OPTIONNAME ] | Истина, если установлен параметр командной оболочки "OPTIONNAME". |
[ -z STRING ] | Истина, если длина строки "STRING" равна нулю. |
[ -n STRING ] или [ STRING ] | Истина, если длина строки "STRING" ненулевая. |
[ STRING1 == STRING2 ] | Истина, если строки равны. Для более строгого соответствия POSIX вместо "==" можно использовать "=". |
[ STRING1 != STRING2 ] | Истина, если строки не равны |
[ STRING1 < STRING2 ] | Истина, если в текущей локали при лексикографической сортировке "STRING1" оказывается перед "STRING2". |
[ STRING1 > STRING2 ] | Истина, если в текущей локали при лексикографической сортировке "STRING1" оказывается после "STRING2". |
[ ARG1 OP ARG2 ] | "OP" — один из операторов -eq, -ne, -lt, -le, -gt или -ge. Эти арифметические двоичные операторы возвращают значение истина, если операнд "ARG1" соответственно равен, не равен, меньше, меньше или равен, больше или больше или равен операнду "ARG2". "ARG1" и "ARG2" являются целыми числами. |
Выражения можно объединять с помощью следующих операторов, перечисляемых в порядке уменьшения их приоритета:
Таблица 7.2. Объединение выражений
Операция | Действие |
[ ! EXPR ] | Истина, если EXPR ложно. |
[ ( EXPR ) ] | Возвращает значение EXPR. Используется для изменения нормального предшествования операторов. |
[ EXPR1 -a EXPR2 ] | Истина, если оба EXPR1 и EXPR2 являются истинными. |
[ EXPR1 -o EXPR2 ] | Истина, если либо EXPR1, либо EXPR2 истинно. |
Оценка значений в условных выражениях осуществляется с помощью встроенной команды [ (или test); при этом используется набор правил, учитывающий число аргументов. Более подробную информацию по этой теме можно найти в документации Bash. Точно также, как if должно закрываться fi, после того, как условия будут перечислены, открывающая квадратная скобка должны быть закрыта закрывающей квадратной скобкой.
В списке CONSEQUENT-COMMANDS, которые идут после инструкции then, может присутствовать любая допустимая команда UNIX, любая исполняемая программа, любой исполняемый скрипт командной оболочки или любая инструкция командной оболочки за исключением закрывающей инструкции fi. Важно помнить, что then и fi считаются в командной оболочке различными инструкциями. Поэтому, когда они набираются в командной строке, их надо разделять точкой с запятой.
В скрипте разные части инструкции if, как правило, хорошо разделены. Ниже приводится несколько простых примеров.
В первом примере проверяется существование файла:
anny ~> cat msgcheck.sh #!/bin/bash echo "This scripts checks the existence of the messages file." echo "Checking..." if [ -f /var/log/messages ] then echo "/var/log/messages exists." fi echo echo "...done." anny ~> ./msgcheck.sh This scripts checks the existence of the messages file. Checking... /var/log/messages exists. ...done.
Для добавления в ваш конфигурационный файл Bash:
# These lines will print a message if the noclobber option is set: if [ -o noclobber ] then echo "Your files are protected against accidental overwriting using redirection." fi
Среда исполнения | |
|
В переменной ? хранится код возврата предыдущей команды (самого последнего процесса, завершенного в фоновом режиме).
В следующем примере показывается простая проверка:
anny ~> if [ $? -eq 0 ] More input> then echo 'That was a good job!' More input> fi That was a good job! anny ~>
В следующем примере демонстрируется, что в TEST-COMMANDS может быть любая команда UNIX, которая возвращает код возврата, и что инструкция if в свою очередь вернет код возврата, который равен нулю:
anny ~> if ! grep $USER /etc/passwd More input> then echo "your user account is not managed locally"; fi your user account is not managed locally anny > echo $? 0 anny >
Тот же самый результат можно получить следующим образом:
anny > grep $USER /etc/passwd anny > if [ $? -ne 0 ] ; then echo "not a local account" ; fi not a local account anny >
В приведенных ниже примерах используется сравнение чисел:
anny > num=`wc -l work.txt` anny > echo $num 201 anny > if [ "$num" -gt "150" ] More input> then echo ; echo "you've worked hard enough for today." More input> echo ; fi you've worked hard enough for today. anny >
Этот скрипт выполняется с помощью cron каждое воскресенье. Если номер недели четный, скрипт напомнит вам почистить мусорную корзину:
#!/bin/bash # Calculate the week number using the date command: WEEKOFFSET=$[ $(date +"%V") % 2 ] # Test if we have a remainder. If not, this is an even week so send a message. # Else, do nothing. if [ $WEEKOFFSET -eq "0" ]; then echo "Sunday evening, put out the garbage cans." | mail -s "Garbage cans out" your@your_domain.org fi
Пример сравнение строк, в котором проверяется идентификатор пользователя:
if [ "$(whoami)" != 'root' ]; then echo "You have no permission to run $0 as non-root user." exit 1; fi
В Bash вы можете сократить этот вид конструкции. Компактный эквивалент приведенной выше проверки будет следующим:
[ "$(whoami)" != 'root' ] && ( echo you are using a non-privileged account; exit 1 )
Точно также, как выражение "&&" указывает, что делать, если проверка возвратит истинное значение, выражение "||" указывает, что делать, если проверка возвратит ложное значение.
В сравнениях также можно использовать регулярные выражения:
anny > gender="female" anny > if [[ "$gender" == f* ]] More input> then echo "Pleasure to meet you, Madame."; fi Pleasure to meet you, Madame. anny >
Практическое программирование | |
|
Не использовать exit? | |
|
Смотрите документацию по Bash для получения дополнительной информации по использованию шаблонов с конструкциями "(( EXPRESSION ))" и "[[ EXPRESSION ]]".
Предыдущий раздел: | Оглавление | Следующий раздел: |
Подводим итоги главы 6 | Расширенные варианты использования конструкции if |