15

Как объявить и использовать логические переменные в shell-скрипте?

10

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

variable=$false

variable=$true

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

if [ $variable ]

if [ !$variable ]

Спасибо за помощь!

5 ответ(ов)

1

Долгий рассказ коротко:

В Bash нет булевых значений

Команды true и false

В Bash есть булевы выражения в терминах сравнения и условий. Однако то, что вы можете объявлять и с чем сравнивать в Bash, — это строки и числа. И на этом всё.

Где бы вы ни встретили true или false в Bash, это либо строка, либо команда/встроенная функция, используемая только для получения кода завершения.

Этот синтаксис...

if true; then ...

по сути аналогичен...

if COMMAND; then ...

где командой является true. Условие истинно в том случае, если команда возвращает код завершения 0. true и false — это встроенные функции Bash, а иногда и отдельные программы, которые ничего не делают, кроме как возвращают соответствующий код завершения.


Условия в if..then..fi

При использовании квадратных скобок или команды test вы полагаетесь на код завершения этой конструкции. Помните, что [ ] и [[ ]] — это тоже просто команды/встроенные функции, как и любые другие. Так что...

if [[ 1 == 1 ]]; then echo yes; fi

соответствует

if COMMAND; then echo yes; fi

где COMMAND здесь — это [[ с параметрами 1 == 1 ]].

Конструкция if..then..fi — это просто синтаксический сахар. Вы всегда можете просто выполнить команды, разделенные двойным амперсандом для того же эффекта:

[[ 1 == 1 ]] && echo yes

При использовании true и false в этих конструкциях тестирования вы на самом деле просто передаете строку "true" или "false" тестовой команде. Вот пример:

Верите или нет, но все эти условия дают один и тот же результат:

if [[ false ]]; then ...
if [[ "false" ]]; then ...
if [[ true ]]; then ...
if [[ "true" ]]; then ...

Кратко: всегда сравнивайте со строками или числами

Для ясности будущим читателям я бы рекомендовал всегда использовать кавычки вокруг true и false:

ДЕЛАЙТЕ

if [[ "${var}" == "true" ]]; then ...
if [[ "${var}" == "false" ]]; then ...
if [[ "${var}" == "yes" ]]; then ...
if [[ "${var}" == "USE_FEATURE_X" ]]; then ...
if [[ -n "${var:-}" ]]; then echo "var is not empty" ...

НЕ ДЕЛАЙТЕ

# Всегда используйте двойные квадратные скобки в bash!
if [ ... ]; then ...
# Это не так ясно и трудно ищется, как -n
if [[ "${var}" ]]; then ...
# Создает впечатление о булевых значениях
if [[ "${var}" != true ]]; then ...
# `-eq` предназначено для чисел и не так легко читается, как `==`
if [[ "${var}" -eq "true" ]]; then ...

Может быть

# Создает впечатление о булевых значениях.
# Может использоваться для строгой проверки опасных операций.
# Это условие ложно для всего, кроме буквальной строки "true".
if [[ "${var}" != "true" ]]; then ... 
0

В вашем скрипте на Bash вы используете арифметические выражения для управления логикой выполнения. Вот перевод вашего скрипта на русский:

#!/bin/bash

false=0
true=1

((false)) && echo false
((true)) && echo true
((!false)) && echo not false
((!true)) && echo not true

Вывод:

true

not false

Объяснение:

  1. Вы задаёте переменные false и true, где false=0 (ложь) и true=1 (истина).
  2. С помощью арифметического выражения ((...)) вы проверяете значения переменных:
    • ((false)) возвращает 0 (ложь), поэтому команда не выполняется, и "false" не выводится.
    • ((true)) возвращает 1 (истина), поэтому "true" выводится.
    • ((!false)) (логическое отрицание) возвращает 1 (истина), так что "not false" выводится.
    • ((!true)) возвращает 0 (ложь), поэтому "not true" не выводится.

Таким образом, вы получаете в выводе только строки "true" и "not false".

0

Вместо того, чтобы имитировать булевое значение и оставлять "ловушку" для будущих читателей, почему бы не использовать более информативные значения, чем просто true и false?

Например:

build_state=success
if что-то-ужасное; then
  build_state=failed
fi

if [[ "$build_state" == success ]]; then
  echo "Иди домой, ты закончил"
else
  echo "У тебя голова горит, бегай по кругу"
fi

Таким образом, вместо использования только двух состояний (успех/неудача) можно иметь различные значения, которые лучше отражают состояние вашей программы. Это делает код более читаемым и понятным для других разработчиков, которые будут с ним работать в будущем.

0

Для управления логикой с использованием булевых значений в Bash, вы можете воспользоваться следующим простым методом, как показано в примере:

# Тесты
var=
var=''
var=""
var=0
var=1
var="abc"
var=abc

if [[ -n "${var}" ]] ; then
    echo 'true'
fi
if [[ -z "${var}" ]] ; then
    echo 'false'
fi

# Результаты
# var=        # false
# var=''      # false
# var=""      # false
# var=0       # true
# var=1       # true
# var="abc"   # true
# var=abc     # true

Если переменная никогда не объявлялась, результат будет: # false.

Таким образом, простой способ установить переменную в значение "истина" (используя этот синтаксический метод) можно сделать, присвоив var=1; в противном случае, чтобы установить ее в "ложь", можно использовать var=''.

Справочная информация:

-n = Истина, если длина строки переменной не равна нулю.

-z = Истина, если длина строки переменной равна нулю.

0

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

first=1  # Истинное значение
second=   # Ложное значение

[ -n "$first" ]  && echo 'Переменная first истинна'
[ -z "$first" ]  && echo 'Переменная first ложна'
[ -n "$second" ] && echo 'Переменная second истинна'
[ -z "$second" ] && echo 'Переменная second ложна'

Результат выполнения:

Переменная first истинна
Переменная second ложна

Вот альтернативный синтаксис тестирования в bash: [[ -n $one ]].

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь