Какова логика проверки истинности/ложности в bash?

Вопрос или проблема

Это:

$ echo $VAR
что-то

И это:

$ [[ -z "$VAR" ]]
$ echo $?
1

Но это:

if [[ -z "$TMUX_MAN_PANE" ]]; then
   echo 'НИКОГДА НЕ ПЕЧАТАЕТ!'

Это меня сбивает с толку.

ОБНОВЛЕНИЕ

Вот немного настоящего кода. Я не могу заставить это работать.

tmux_man_page() {
if [[ "$TERM" =~ 'screen' ]] && [[ -n "$TMUX" ]]; then
  tmux list-panes -t $TMUX_MAN_PANE &> /dev/null
  echo $?
  echo $TMUX_MAN_PANE
  [[ -z "$TMUX_MAN_PANE" ]]
  echo $?
  if ! [[ -z "$TMUX_MAN_PANE" ]] && [[ $? ]]; then
    echo debug1
    tmux -q respawn-pane -k -t $TMUX_MAN_PANE man $1
  else
    echo debug2
    tmux split-window -vf man $1
    TMUX_MAN_PANE=$(tmux display-message -p "#{pane_id}")
    export TMUX_MAN_PANE
    tmux select-pane -t {last}
  fi
fi
}

ОБНОВЛЕНИЕ 2: Успех

Наконец-то разобрался. Были проблемы с получением статуса первой строки в операторе if. Пришлось прибегнуть к хитрости, чтобы получить вывод оператора tmux в первой строке оператора if. Если кто-то знает более чистый способ сделать это, я весь во внимании.

Вот рабочий код:

tmux_man_page() {
if [[ "$TERM" =~ 'screen' ]] && [[ -n "$TMUX" ]]; then
  pane=$(tmux list-panes -t $TMUX_MAN_PANE 2>&1)
  if ! [[ -z "$TMUX_MAN_PANE" ]] && ! [[ $pane =~ 'find pane' ]]; then
    tmux -q respawn-pane -k -t $TMUX_MAN_PANE man $1
  else
    tmux split-window -vf man $1
    TMUX_MAN_PANE=$(tmux display-message -p "#{pane_id}")
    export TMUX_MAN_PANE
    tmux select-pane -t {last}
  fi
fi
}

tmux_man_page_close() {
  if [ $TMUX_MAN_PANE ]; then
     tmux kill-pane -t $TMUX_MAN_PANE
  fi
}

Ключ в том, что код возврата 0 означает истину/успех, а 1 (или любое другое ненулевое значение) означает ложь/неудачу.

В оболочке проверка, которая является истиной (т.е. программа, которая успешно завершилась), возвращает код 0. Проверка [[ -z "$VAR" ]] возвращает код ноль (истина), если $VAR пусто, или один (ложь), если оно не пусто:

$ var=""; [[ -z "$var" ]]; echo $?
0
$ var="НЕ ПУСТО"; [[ -z "$var" ]]; echo $?
1

В итоге, если $VAR не пусто, то [[ -z "$VAR" ]] ложно (возвращает 1), и оператор then не выполняется.

Вы хотели, чтобы проверка возвращала истину, если переменная не пустая? Если да, замените -z на -n:

$ var=""; [[ -n "$var" ]]; echo $?
1
$ var="НЕ ПУСТО"; [[ -n "$var" ]]; echo $?
0

Для краткости та же проверка выполняется, если -n опущен:

$ var=""; [[ "$var" ]]; echo $?
1
$ var="НЕ ПУСТО"; [[ "$var" ]]; echo $?
0

(Обратите внимание, что в арифметическом контексте истинностные значения такие же, как и в большинстве языков программирования, где ноль рассматривается как ложь. Так, например, if (( a )); then echo "$a is non-zero"; fi. Но арифметические проверки также соблюдают эту конвенцию, так что вы получаете правильное поведение с (( a != 0 )) тоже.)

Ответ или решение

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

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

  1. Код выхода 0: означает, что выражение успешно и истинно.
  2. Код выхода 1 или любая другая не-нулевая величина: означает, что выражение ложно или завершилось с ошибкой.

Теперь к вашему примеру:

Когда вы используете команду [[ -z "$VAR" ]], Bash проверяет, пустая ли переменная VAR. Опция -z означает "zero-length" или "нулевая длина", и она возвращает истину (0), если переменная пустая. Следовательно, если VAR содержит какое-либо значение, выражение [[ -z "$VAR" ]] будет возвращать ложь (1).

Пример иллюстрирует это легко:

var=""; [[ -z "$var" ]]; echo $?
# Вывод: 0, поскольку var пустая

var="NOT EMPTY"; [[ -z "$var" ]]; echo $?
# Вывод: 1, поскольку var не пустая

Если ваша цель в том, чтобы проверить, является ли переменная НЕ пустой, следует использовать обратный оператор -n, который возвращает истину (0), если переменная имеет значение:

var=""; [[ -n "$var" ]]; echo $?
# Вывод: 1, поскольку var пустая

var="NOT EMPTY"; [[ -n "$var" ]]; echo $?
# Вывод: 0, поскольку var не пустая

Следует отметить, что если вы просто используете [[ "$var" ]], это равнозначно проверке [[ -n "$var" ]] и будет возвращать истину (0), если переменная не пустая, и ложь (1), если пустая.

В вашем случае, когда вначале была путаница с проверкой на [[ -z "$TMUX_MAN_PANE" ]], код работал так, что выражение возвращает ложь, если TMUX_MAN_PANE непустая, и условный блок then не выполняется.

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

Поскольку вопрос был связан с примерами из контекста скриптов в Bash, вы всегда должны убедиться, что правильно используете операторы, соответствующие вашей логике программы, и что выбранные операторы отражают ваше намерение достижения функциональности.

Оптимизация SEO: Включение ключевых слов, таких как Bash, проверка условий в Bash, операторы проверки переменных в Bash, добавят ценность для людей, ищущих информацию об этой теме.

Оцените материал
Добавить комментарий

Капча загружается...