1
$ false
$ echo $?
1

$ if [[ false ]]; then echo 'do it'; fi
do it

$ test false && echo 'do it'
do it

$ COND=false
$ echo $COND
false
$ if [[ $COND -ne 0 ]]; then echo 'do it'; fi
$ if [[ $COND -ne true ]]; then echo 'do it'; fi

Это ерунда ИМО, что мне здесь не хватает?

-- Обновить

Итак, вот как это происходит:

$ COND=false
$ if ! $COND; then echo 'do it'; fi
do it
$ if $COND; then echo 'do it'; fi

Но я хочу объединить $COND с другими условными выражениями в одном большем тестовом выражении (или [[ {expr} && {expr} ]]). Поэтому, когда $COND имеет значение false, он не работает внутри [[ {expr} ]] интуитивно понятным способом. Кажется, [[ {expr} ]] немного вводит в заблуждение, когда то, что мне нужно, больше похоже на:

$ COND=false
$ if ! $COND && test -d ${HOME}/bin ; then echo 'do it'; fi
do it

2 ответа2

2

Синтаксис оболочки сильно зависит от контекста. То есть то, что конкретная вещь (например, true или false) означает, во многом зависит от того, где она происходит. В ваших примерах false имеет три совершенно разных значения: команда, строковое значение и (несуществующее) имя переменной, содержащей целочисленное значение. Позвольте мне пробежаться по примерам:

  • false как команда:

    false; echo $?    # prints "1"
    if false; then echo "yep"; else echo "nope"; fi    # prints "nope"
    

    Есть команда с именем "false" (обычно /usr /bin /false или встроенная команда bash, которая делает то же самое), которая на самом деле ничего не делает, кроме выхода со статусом сбоя. В качестве состояния выхода ноль указывает на успех (что-то вроде правды), а ненулевой указывает на неудачу (что-то вроде ложного). Это противоположно более обычному соглашению ноль = ложь, ненулевое = истина, но для состояний выхода это имеет больше смысла.

  • false как не интерпретированное строковое значение:

    if [[ false ]]; then echo "yep"; else echo "nope"; fi     # prints "yep"
    if [[ true ]]; then echo "yep"; else echo "nope"; fi      # prints "yep"
    if [[ wibble ]]; then echo "yep"; else echo "nope"; fi    # prints "yep"
    if [[ "this is a string" ]]; then echo "yep"; else echo "nope"; fi    # prints "yep"
    [[ false ]]; echo $?    # prints "0" (=success)
    [ false ]; echo $?      # prints "0" (=success)
    test false; echo $?     # prints "0" (=success)
    

    Во всех этих случаях команда test или ее синоним [ или условное выражение bash [[ ]] не получили выражения, только одну строку, поэтому они выполняют очень простой тест: это строка ненулевой длины? "true", "false", "wibble" и т. д. имеют ненулевую длину, поэтому команда / выражение подобна истине и, следовательно, успешна. Сравнить с:

    [[ "" ]]; echo $?    # prints "1" (=failure), because the string is zero-length
    [[ ]]; echo $?       # prints "1" (=failure), because there isn't even a string
    [ ]; echo $?         # same
    

    Обратите внимание, что test и [ являются обычными командами, а "false" (и "wibble" и т.д.) - это просто аргумент. [[ ]] это немного синтаксиса bash, который можно использовать вместо команды. Их аргументы / содержимое анализируются не так, как имена команд.

  • false как возможное имя переменной, которая может содержать целое число:

    if [[ false -eq true ]]; then echo "equal"; else echo "nope"; fi     # prints "equal"
    

    Это немного страннее и зависит от деталей того, как bash [[ ]] проверяет числовое равенство. Обратите внимание, что в [[ ]][ ] и test выражениях) -eq проверяет равенство чисел и = проверяет равенство строк. Так, например, [[ 01 -eq 1 ]] (потому что 1 и 01 численно равны) является истиной, но [[ 01 = 1 ]] является ложью (потому что они не являются одной и той же строкой). В случае [[ false -eq true ]] "true" и "false" не являются целочисленными значениями, поэтому bash пытается преобразовать их в целые числа, обрабатывая их как имена переменных (и надеясь, что переменные содержат целочисленные значения). На самом деле, ни одна из них не определена как переменная, поэтому они оба оценивают пустую строку, которая может быть интерпретирована как целое число 0. Заметим:

    if [[ false -eq true ]]; then echo "equal"; else echo "nope"; fi     # prints "equal"
    if [[ false -eq 0 ]]; then echo "equal"; else echo "nope"; fi        # prints "equal"
    false=5
    if [[ false -eq true ]]; then echo "equal"; else echo "nope"; fi     # now prints "nope"
    

    Обратите внимание, что определение false в качестве переменной не влияет на другие ее применения; при использовании в качестве команды он по-прежнему завершается со статусом 1, а при использовании в качестве строки он все еще просто "ложь" (не "5").

1

Вы не запускаете команду false , но используете [[ (аналогично командам test и [ встроенные команды)), чтобы оценить выражение "false", и не давая ему ничего другого для оценки, он делает это:

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

Смотрите раздел УСЛОВНЫЕ ВЫРАЖЕНИЯ man bash для получения дополнительной информации.

if же выполнить команду дал, а затем проверяет его статус выхода.

[Ссылка любезно ответ от SO ]

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .