Условные операторы if..else командной оболочки Bash
Bash if..else Statement
В этом руководстве мы познакомим вас с основами if оператора Bash и покажем, как его использовать в сценариях оболочки
Принятие решений — одна из самых фундаментальных концепций компьютерного программирования. Как и в любом другом языке программирования, if , if..else , if..elif..else и вложенные if в Bash могут быть использованы для выполнения кода на основе определенного состояния.
Условия Bash if могут иметь разные формы. Самое основное утверждение if принимает следующую форму:
Если TEST-COMMAND оценивается как True , STATEMENTS выполняется. Если TEST-COMMAND возвращается False , ничего не происходит, STATEMENTS игнорируется.
Как правило, рекомендуется всегда делать отступы для вашего кода и отделять блоки кода пустыми строками. Большинство людей предпочитают использовать отступы с 4 или 2 пробелами. Отступы и пустые строки делают ваш код более читабельным и упорядоченным.
Давайте посмотрим на следующий пример сценария, который проверяет, больше ли заданное число, чем 10:
Сохраните код в файле и запустите его из командной строки:
Скрипт предложит вам ввести номер. Например, если вы введете 15, test команда выполнит оценку, true потому что 15 больше 10, и echo команда внутри then условия будет выполнена.
if..else
Оператор Bash if..else принимает следующую форму:
Если TEST-COMMAND оценка до True , STATEMENTS1 будет выполнен. В противном случае, если TEST-COMMAND возвращается False , STATEMENTS2 будет выполнен. Вы можете иметь только одно else условие в объявлении.
Давайте добавим else условие в предыдущий пример сценария:
Если вы запустите код и введете число, сценарий напечатает другое сообщение в зависимости от того, больше это число или меньше / равно 10.
if..elif..else
Оператор Bash if..elif..else принимает следующую форму:
Вы можете иметь одно или несколько elif условий в объявлении. else Пункт не является обязательным.
Условия оцениваются последовательно. Как только условие возвращается, True остальные условия не выполняются, и управление программой переходит к концу if операторов.
Давайте добавим условие elif к предыдущему сценарию:
Вложенные if
Bash позволяет вам вкладывать if утверждения в if утверждения. Вы можете разместить несколько if операторов внутри другого if оператора.
Следующий скрипт предложит вам ввести три числа и напечатает наибольшее число среди трех чисел.
Вот как будет выглядеть вывод:
Как правило, более эффективно использовать case оператор вместо вложенных if операторов.
Несколько условий
Логические OR и AND операторы позволяют использовать несколько условий в if выражениях.
Вот еще одна версия скрипта для печати наибольшего числа среди трех чисел. В этой версии вместо вложенных if операторов мы используем оператор логического AND ( && ).
Тестовые операторы
В Bash команда test принимает одну из следующих синтаксических форм:
Чтобы сделать скрипт переносимым, предпочтите использовать старую [ команду test, которая доступна во всех оболочках POSIX. Новая обновленная версия test команды [[ (двойные скобки) поддерживается в большинстве современных систем, использующих Bash, Zsh и Ksh в качестве оболочки по умолчанию.
Чтобы отменить тестовое выражение, используйте логический оператор NOT ( ! ). При сравнении строк всегда используйте одинарные или двойные кавычки, чтобы избежать проблем с разбивкой слов.
Ниже приведены некоторые из наиболее часто используемых операторов:
- -n VAR — Истина, если длина VAR больше нуля.
- -z VAR — Правда, если VAR пусто.
- STRING1 = STRING2 — Правда, если STRING1 и STRING2 равны.
- STRING1 != STRING2 — Правда если STRING1 и STRING2 не равны.
- INTEGER1 -eq INTEGER2 — Правда, если INTEGER1 и INTEGER2 равны.
- INTEGER1 -gt INTEGER2 — Верно, если INTEGER1 больше чем INTEGER2 .
- INTEGER1 -lt INTEGER2 — Правда, если INTEGER1 меньше, чем INTEGER2 .
- INTEGER1 -ge INTEGER2 — Истинно, если INTEGER1 равно или больше, чем INTEGER2.
- INTEGER1 -le INTEGER2 — Верно, если INTEGER1 равно или меньше чем INTEGER2 .
- -h FILE — Истина, если FILE существует и является символической ссылкой.
- -r FILE — Истинно, если FILE существует и доступно для чтения.
- -w FILE — Истина, если FILE существует и доступна для записи.
- -x FILE — True, если FILE существует и является исполняемым.
- -d FILE — True, если FILE существует и является каталогом.
- -e FILE — Истинно, если FILE существует и является файлом, независимо от типа (узел, каталог, сокет и т. Д.).
- -f FILE — True, если FILE существует и является обычным файлом (не каталогом или устройством).
Вывод
Операторы if , if..else and if..elif..else позволяют контролировать поток выполнения скрипта Bash, оценивая заданные условия.
Источник
Linux bash if numbers
Условия в скриптах bash (условные операторы)
В Bash имеется множество встроенных проверок и сравнений, что очень удобно во многих ситуациях. Вы, наверное, видели, если такие заявления раньше:
Условие в этом примере по сути является командой. Это может звучать странно, но сравнение с квадратными скобками аналогично использованию встроенной команды test , например:
Если $foo больше(G) или равно(E) 3, блок после «then» будет выполнен. Если вы всегда задавались вопросом, почему bash использует -ge или -eq вместо >= или ==, это потому, что этот тип условия исходит из команды, где -ge и -eq — параметры. И это то, что по сути, проверяет состояние завершения команды. Я объясню это более подробно далее в руководстве. Также есть встроенные проверки, которые более специфичны для оболочек.
Вышеуказанное условие выполняется, если файл «regularfile» существует и это обычный файл. Обычный файл означает, что это не блок или символьное устройство или каталог. Таким образом, вы можете быть уверены, что Файл существует, прежде чем что-то делать с ним. Вы даже можете проверить, если файл читабелен!
Приведенное выше условие выполняется, если файл «readablefile» существует и доступен для чтения. Легко, не правда ли?
Синтаксис оператора if (краткое объяснение)
Основной синтаксис оператора if … then выглядит следующим образом:
Условие, в зависимости от его типа, окружено определенным скобки, например. []. Вы можете прочитать о различных типах дальше в учебнике. Вы можете добавить команды, которые будут выполняться, когда условие ложно, с помощью ключевого слова else и использовать ключевое слово elif (elseif) для выполнения команд с другим условием, если основное условие ложно. Ключевое слово else всегда стоит последним. Пример:
Краткое объяснение примера: сначала мы проверяем, является ли файл somefile читаемым («if [-r somefile ]»). Если так, мы читаем это в переменную. Если нет, мы проверяем, существует ли он на самом деле («elif [-f somefile ]»). Если это правда, мы сообщаем, что он существует, но не читается (если бы это было так, мы бы прочитали содержимое). Если файл не существует, мы также сообщаем об этом. Условие в elif выполняется только в том случае, если условие в if было ложным. Команды, принадлежащие else, выполняются, только если оба условия ложны.
Основные правила условий
Когда вы начинаете писать и использовать свои собственные условия, вы должны знать некоторые правила, чтобы избежать ошибок, которые трудно отследить. Вот три важных:
Всегда оставляйте пробелы между скобками и фактической проверкой/сравнением. Следующие не будут работать:
Баш будет жаловаться на “отсутствуoщий ‘]’”.
Всегда заканчивайте строку перед введением нового ключевого слова, такого как «then». Слова if, then, else, elif и fi являются ключевыми словами оболочки, что означает, что они не могут использовать одну и ту же строку. Поместите «;» между предыдущим оператором и ключевым словом или поместите ключевое слово в начале новой строки. Bash будет выдавать ошибки, такие как «ошибка синтаксиса, рядом с неожиданным токеном «fi», если вы этого не сделаете.
Это хорошая привычка заключать в кавычки строковые переменные, если вы используете их в условиях, потому что в противном случае они могут создать проблемы, если они содержат пробелы и/или символы новой строки. Цитируя я имею в виду:
Есть несколько случаев, в которых вы не должны экранировать ковычками, но они редки. Вы увидите одну из них далее в руководстве.
Кроме того, есть две вещи, которые может быть полезно знать:
Вы можете инвертировать условие, поставив перед ним «!». Пример:
Обязательно поместите «!» В скобки!
Вы можете комбинировать условия с помощью определенных операторов. Для синтаксиса с одной скобкой, который мы использовали до сих пор, вы можете использовать «-a» для and и «-o» для or. Пример:
Приведенное выше условие вернет true, если $foo содержит целое число, большее или равное 3 и меньшее (Less Than) 10. Подробнее об этих выражениях объединения можно прочитать в соответствующих синтаксисах условий.
И еще одна базовая вещь: не забывайте, что условия могут также использоваться в других операторах, таких как while и until. Объяснение этого не входит в этот урок, но вы можете прочитать о них в Руководстве по Bash для начинающих.
Во всяком случае, я пока показал вам только условия в одинарных скобках. Однако есть и другие синтаксисы, о которых вы узнаете в следующем разделе.
Различные синтаксисы условий
Bash имеет различные синтаксисы для условий. Я перечислю три из них:
1. Синтаксис с одной скобкой
Это синтаксис условия, который вы уже видели в предыдущих параграфах; это самый старый поддерживаемый синтаксис. Он поддерживает три типа условий:
Файловые условия
Позволяет различные виды проверок. Пример:
Приведенное выше условие верно, если файл символическая ссылка существует и является символической ссылкой. Дополнительные условия для файлов см. в таблице ниже.
Строковые условия
Позволяет проверять строку и сравнивать строки. Пример первый:
Вышеуказанное условие истинно, если $emptystring является пустой строкой или неинициализированной переменной. Пример два:
Приведенное выше условие истинно, если $stringvar1 содержит только строку «cheese». Дополнительные условия на основе строк см. в таблице ниже.
Арифметические (числовые) условия
Позволяет сравнивать целые числа. Пример:
Приведенное выше условие возвращает true, если $num меньше 1. Более подробные арифметические условия см. в таблице ниже.
2. Синтаксис в двойных скобках
Возможно, вы уже столкнулись с условиями, заключенными в двойные квадратные скобки, которые выглядят так:
Синтаксис двойной скобки служит расширенной версией синтаксиса одной скобки; он в основном имеет те же особенности, но и некоторые важные различия с ним. Я перечислю их здесь:
Первое отличие_ можно увидеть в приведенном выше примере; при сравнении строк в синтаксисе двойных скобок используется глобализация оболочки(shell globbing). Это означает, что звездочка («*») расширится буквально до чего угодно, как вы, вероятно, знаете из обычного использования командной строки. Поэтому, если $stringvar где-либо содержит фразу «string», условие вернет true. Допускаются и другие формы срыва оболочки. Если вы хотите сопоставить и строку «String», и строку «string», вы можете использовать следующий синтаксис:
Обратите внимание, что допускается только общее глобирование оболочки. Такие Bash-специфичные вещи, такие как <1..4>или
Второе отличие — это то, что разделение слов предотвращено. Следовательно, вы можете опустить размещение кавычек вокруг строковых переменных и без проблем использовать условие, подобное следующему:
Тем не менее, цитирование строковых переменных остается хорошей привычкой, поэтому я рекомендую просто продолжать это делать.
Третье отличие состоит в том, что имена файлов не расширяются. Я проиллюстрирую это различие на двух примерах, начиная со старой ситуации с одной скобкой:
Вышеуказанное условие вернет true, если в рабочем каталоге есть один файл с расширением .sh. Если их нет, он вернет false. Если есть несколько файлов .sh, bash выдаст ошибку и прекратит выполнение скрипта. Это связано с тем, что *.sh распространяется на файлы в рабочем каталоге. Использование двойных скобок предотвращает это:
Приведенное выше условие вернет true, только если в рабочем каталоге есть файл с именем «*.sh», независимо от того, какие существуют другие файлы .sh. Звездочка взята буквально, потому что синтаксис в двойных скобках не расширяет имена файлов.
Четвертое отличие — это добавление более общеизвестных объединяющих выражений или, более конкретно, операторов «&&» и «||». Пример:
Приведенное выше условие возвращает true, если $num равно 3, а $stringvar равно «foo». Также поддерживаются -a и -o, известные из синтаксиса с одной скобкой.
Обратите внимание, что оператор and имеет приоритет над оператором or, что означает, что «&&» или «-a» будет оцениваться перед «||» или «-о».
Пятое отличие состоит в том, что синтаксис в двойных скобках позволяет сопоставлять шаблоны с помощью оператора «=
». Смотрите таблица для получения дополнительной информации.
3. Синтаксис с двойными скобками
Существует также другой синтаксис для арифметических (основанных на числах) условий, наиболее вероятно взятый из оболочки Korn:
Приведенное выше условие выполняется, если $num меньше или равно 5. Этот синтаксис может показаться программистам более знакомым. Он включает в себя все «нормальные» операторы, такие как ==, и =>. Он поддерживает комбинирующие выражения «&&» и «||» (но не выражения -a и -o!). Это эквивалентно встроенной команде let.
В следующей таблице перечислены возможные условия для синтаксиса с одинарными и двойными скобками. За исключением одного исключения, примеры приведены в синтаксисе с одинарными скобками, но всегда совместимы с двойными скобками.
1. File-based conditions:
rm -f tmp.tmp # Make sure we’re not bothered by an old temporary file
fi
if [ -b /dev/fd0 ]; then
dd if=floppy.img of=/dev/fd0 # Write an image to a floppy
fi
if [ -c /dev/dsp ]; then
cat raw.wav > /dev/dsp # This actually works for certain raw wav files
fi
/.kde ]; then
echo “You seem to be a kde user.”
fi
if [ -g . ]; then
echo “Created files are inheriting the group ‘$(ls -ld . | awk ‘< print $4 >’)’ from the working directory.”
fi
if [ ! -G file ]; then # An exclamation mark inverts the outcome of the condition following it
chgrp $(id -g) file # Change the group if it’s not the effective one
fi
pathtofile=$(readlink -e $pathtofile) #Make sure $pathtofile contains the actual file and not a symlink to it
fi
if [ ! -k /tmp ]; then # An exclamation mark inverts the outcome of the condition following it
echo “Warning! Anyone can delete and/or rename your files in /tmp!”
fi
killall -HUP crond # SIGHUP makes crond reread all crontabs
fi
chmod 600 file # Makes the file private, which is a bad idea if you don’t own it
fi
if [ -p $file ]; then
cp $file tmp.tmp # Make sure we’ll be able to read
file=”tmp.tmp” # the file as many times as we like
fi
content=$(cat file) # Set $content to the content of the file
fi
gzip logfile # Backup the old logfile
touch logfile # before creating a fresh one.
fi
if [ -S /var/lib/mysql/mysql.sock ]; then
mysql –socket=/var/lib/mysql/mysql.sock #See this MySQL tip
fi
if [ -t /dev/pts/3 ]; then
echo -e “nHello there. Message from terminal $(tty) to you.” > /dev/pts/3 #Anyone using that terminal will actually see this message!
fi
if [ -u executable ]; then
echo “Running program executable as user $(ls -l executable | awk ‘< print $3 >’).”
fi
grub-install /dev/hda
fi
if [ -x /root ]; then
echo “You can view the contents of the /root directory.”
fi
echo “story.txt1 is newer than story.txt; I suggest continuing with the former.”
fi
cp -f localfile /mnt/remote/remotefile # Make sure the remote location has the newest version of the file, too
fi
echo “Your primary cd drive appears to read dvd’s, too.”
fi
2. String-based conditions:
echo $cow # Ever tried executing ‘apt-get moo’?
fiNote: you can also use a single “=” instead of a double one.
echo “Access denied! Wrong password!”
exit 1 # Stops script execution right here
fi
(Don’t feel ashamed if you don’t understand this, it is a more complex example)
array=( linux tutorial blog )
swaps=1
while (( swaps > 0 )); do
swaps=0
for (( i=0; i “$
tempstring=$
array[$i]=$
array[$(( i + 1 ))]=$tempstring
(( swaps=swaps + 1 ))
fi
done
done
echo $
fi
Note that you can also omit the “-n”, as brackets with just a string in it behave the same.
if [ -z $uninitializedvar ]; then
uninitializedvar=”initialized” # -z returns true on an uninitialized variable, so we initialize it here.
fi
[[ STRING1 =
REGEXPATTERN ]]
“b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+.[A-Za-z]<2,4>b” ]]; then
echo “$email contains a valid e-mail address.”
fi
3. Arithmetic (number-based) conditions:
if [ $? -eq 0 ]; then # $? returns the exit status of the previous command
echo “Previous command ran succesfully.”
fi
if [ $(ps -p $pid -o ni=) -ne $(nice) ]; then
echo “Process $pid is running with a non-default nice value”
fi
if [ $num -lt 0 ]; then
echo “Negative numbers not allowed; exiting…”
exit 1
fi
4. Miscellaneous conditions:
if [ ! -o checkwinsize ] # An exclamation mark inverts the outcome of the condition following it
echo “Shell option checkwinsize is disabled; enabling it so you can resize you terminal window without problems.”
shopt -s checkwinsize # This shell option is modifiable
fi
if [ -o login_shell ]; then
echo “This a a login shell.” # This shell option is not modifiable
fi
С помощью синтаксиса с двойными круглыми скобками вы можете использовать следующие условия:
5. Double-parenthesis syntax conditions:
if (( $? == 0 )); then # $? returns the exit status of the previous command
echo “Previous command ran succesfully.”
fi
if (( $(ps -p $pid -o ni=) != $(nice) )); then
echo “Process $pid is running with a non-default nice value”
fi
if (( $num NUM2 ))
Погружение немного глубже
Я сказал, что расскажу больше о том, что if по существу проверяет состояние завершения команд. И я так и сделаю. Основное правило bash, когда дело доходит до условий: 0 равно true, >0 равно false. Это в значительной степени противоположно многим языкам программирования, где 0 равно false, а 1 (или более) равно true. Причиной этого является то, что оболочки типа bash часто работают с программами. По соглашению UNIX программы используют состояние выхода для указания того, что выполнение прошло нормально или произошла ошибка. Поскольку успешное выполнение не требует каких-либо объяснений, ему нужен только один статус выхода. Однако, если возникла проблема, полезно знать, что пошло не так. Следовательно, 0 используется для успешного выполнения, а 1-255 для указания, какая ошибка произошла. Значения чисел 1-255 различаются в зависимости от программы, возвращающей их.
В любом случае, if выполняет блок после then, когда команда возвращает 0. Да, условия являются командами. Фраза [$ foo -ge 3 ] возвращает статус завершения, а также два других синтаксиса! Следовательно, есть удобный прием, который вы можете использовать для быстрого тестирования состояния:
В этом примере «echo true» выполняется только в том случае, если [$ foo -ge 3 ] возвращает 0 (true). Почему это так, спросите вы? Это потому, что bash оценивает состояние только при необходимости. При использовании комбинирующего выражения and оба условия должны быть истинными, чтобы комбинированное выражение возвращало true. Если первое условие возвращает false, не имеет значения, что возвращает второе; результат будет ложным. Следовательно, bash не оценивает второе условие, и именно поэтому в этом примере «echo true» не выполняется. То же самое относится к оператору or («||»), где второе условие не оценивается, если первое условие истинно.
Источник