У Bash немає поняття булевих значень (англ. Boolean). Є рядки тексту (англ. string) та числа, а також масиви рядків тексту чи чисел. Тож як умовні команди працюють із правдою та неправдою?
Команди після завершення роботи повертають статус виходу. Статус виходу - це ціле число від 0 до 255 включно. Bash вважає статус виходу нуль ознакою успіху. Будь-який інший статус виходу означає невдачу.
Це стосується всіх команд, зокрема вбудованих команд bash, ключових слів і функцій.
Базовий синтаксис команди if такий:
if CONDITIONAL_COMMANDS; then TRUE_COMMANDS; else FALSE_COMMANDS; fi
Вона починається з if; умовні команди відокремлюються від команд «успіху» словом then; а завершується вона словом fi.
Гілка else необовʼязкова.
CONDITIONAL_COMMANDS може бути однією командою або списком команд.
Умовні команди виконуються, і
Каскадні розгалуження можна задати за допомогою elif
if CONDITIONAL_COMMANDS
then TRUE_COMMANDS
elif CONDITIONAL_COMMANDS_2
then TRUE_COMMANDS_2
# more elif branches ...
else FALSE_COMMANDS
fi
Перед словами then, elif, else і fi має бути крапка з комою або новий рядок.
Наголосимо: саме статус виходу умовних команд керує потоком виконання.
Наприклад, grep повертає 0, якщо збіг знайдено, і 1, якщо збігу немає.
Опція -q пригнічує виведення, залишаючи лише статус виходу.
if grep -q "my pattern" my_file; then echo "the pattern is found in the file"; fi
Навколо CONDITIONAL_COMMANDS немає жодного спеціального синтаксису. Можливо, ми звикли до умовних конструкцій такого вигляду:
if [ "$password" = "secure" ]; then
echo "Welcome!"
fi
[ не є спеціальним синтаксисом.
Це команда, яка обчислює умовний вираз і завершується зі статусом успіху чи невдачі.
Як і для всіх команд, між нею та її аргументами обовʼязковий пробіл.
Насправді [ - це синонім команди test.
Вони абсолютно однакові, хіба що останній аргумент [ мусить бути ].
Усередині [ і ] ми записуємо умовний вираз.
Ось кілька типових умовних виразів:
[ -f "$filename" ] # file operations
[ "$string1" = "$string2" ] # string comparisons
[ "$num1" -eq "$num2" ] # arithmetic comparisons
Доступних операцій набагато більше; вони перелічені в розділі Bash Conditional Expressions посібника.
У наведених вище прикладах звернімо увагу: усі змінні взято в лапки.
Команди test і [ - це звичайні команди, у яких аргументи підлягають розбиттю на слова та розкриттю імен файлів, як і в будь-якій іншій команді.
Це важливо зазначити, бо умовні вирази обчислюються по-різному залежно від того, скільки аргументів ми надаємо:
[ -z "$name" ]) або ! (заперечення статусу тесту з 1 аргументом)Ми можемо дістати несподівані результати, якщо забудемо взяти змінну в лапки:
str=""
# this prints "empty"
if [ -n "$str" ]; then echo "not empty"; else echo "empty"; fi
# leaving the variable unquoted results in incorrect "not empty" output
if [ -n $str ]; then echo "not empty"; else echo "empty"; fi
Конструкція [[...]] - не команда, а ключове слово.
Це означає, що хоч із нею поводяться як із будь-якою іншою командою, вона має особливі правила розбору.
Особливість [[ у тому, що змінні, розкриті всередині неї, не підлягають розбиттю на слова чи розкриттю імен файлів.
Тобто ця команда поводиться так, як ми й очікуємо, навіть без лапок.
if [[ -n $str ]]; then echo "not empty"; else echo "empty"; fi
[[ підтримує всі умовні вирази, з якими вміють працювати test і [.
Крім того, [[ надає
=~,== і !=, які працюють як оператори зіставлення зі взірцем,&& (логічне і) та || (логічне або) як логічні оператори (особливе правило розбору),< і >, які працюють як «голі» оператори порівняння рядків тексту (особливе правило розбору: оскільки це символи перенаправлення, у [ їх потрібно екранувати).Поширена думка, що ці особливі можливості дають настільки велику перевагу, що [[ варто використовувати завжди.
(Наприклад, Google Shell Style Guide.)
case - ще одна команда керування потоком виконання.
Вона схожа на конструкцію «switch» в інших мовах.
case WORD in [PATTERN [| PATTERN]...) COMMANDS ;;]... esac
WORD зіставляється з кожним PATTERN. Коли один із них збігається, виконуються COMMANDS.
read -p "Guess the secret word: " word
case "$word" in
secret) echo "Yes, you guessed it!" ;;
??????) echo "That's the right number of letters." ;;
s*) echo "You guessed the first letter." ;;
*) echo "Not even close! Try again." ;;
esac
Кожна гілка COMMANDS має закінчуватися двома крапками з комою, ;;.