Треки
/
Bash
Bash
/
Салабус
/
Умовні конструкції
Ум

Умовні конструкції у Bash

{one: "1 вправа", few: "%{count} вправи", many: "%{count} вправ", other: "%{count} вправи"}

Про концепцію Умовні конструкції

Що вважається правдою в Bash

У Bash немає поняття булевих значень (англ. Boolean). Є рядки тексту (англ. string) та числа, а також масиви рядків тексту чи чисел. Тож як умовні команди працюють із правдою та неправдою?

Статус виходу

Команди після завершення роботи повертають статус виходу. Статус виходу - це ціле число від 0 до 255 включно. Bash вважає статус виходу нуль ознакою успіху. Будь-який інший статус виходу означає невдачу.

Це стосується всіх команд, зокрема вбудованих команд bash, ключових слів і функцій.

Команда «if»

Базовий синтаксис команди if такий:

if CONDITIONAL_COMMANDS; then TRUE_COMMANDS; else FALSE_COMMANDS; fi

Вона починається з if; умовні команди відокремлюються від команд «успіху» словом then; а завершується вона словом fi. Гілка else необовʼязкова.

CONDITIONAL_COMMANDS може бути однією командою або списком команд.

Умовні команди виконуються, і

  • якщо статус виходу нульовий (успіх), то виконуються TRUE_COMMANDS.
  • якщо статус виходу ненульовий (невдача), то виконуються FALSE_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

Команди «[» і «test»

Навколо 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 посібника.

Note

У наведених вище прикладах звернімо увагу: усі змінні взято в лапки. Команди test і [ - це звичайні команди, у яких аргументи підлягають розбиттю на слова та розкриттю імен файлів, як і в будь-якій іншій команді.

Це важливо зазначити, бо умовні вирази обчислюються по-різному залежно від того, скільки аргументів ми надаємо:

  • 0 аргументів: статус виходу ненульовий (невдача)
  • 1 аргумент: статус виходу нульовий (успіх), якщо аргумент непорожній, і ненульовий, якщо він порожній.
  • 2 аргументи: перший аргумент має бути унарним оператором (наприклад, [ -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»

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 має закінчуватися двома крапками з комою, ;;.

Note
  1. Є альтернативи, які забезпечують наскрізне виконання команд і продовження зіставлення зі взірцем. Докладніше дивімося в посібнику.
  2. Пригадаймо, що ми говорили про взірці в розділі Filename Expansion концепції «Лапки».
Редагувати через GitHub Посилання відкривається в новому вікні або вкладці