На этой неделе изучал bash и столкнулся с загадкой.
#!/bin/sh
if [ false ]; then
echo "True"
else
echo "False"
fi
Это всегда будет выводить True, хотя условие может показывать иначе. Если я снимаю скобки, []
то это работает, но я не понимаю, почему.
bash
conditional-operator
tenmiles
источник
источник
#!/bin/sh
не bash-скрипта, это POSIX sh-скрипт. Даже если интерпретатор POSIX sh в вашей системе предоставляется bash, он отключает несколько расширений. Если вы хотите писать сценарии bash, используйте#!/bin/bash
или его локально соответствующий эквивалент (#!/usr/bin/env bash
чтобы использовать первый интерпретатор bash в PATH).[[ false ]]
тоже влияет .Ответы:
Вы запускаете команду
[
(akatest
) с аргументом «ложь», а не запускаете командуfalse
. Поскольку "false" - непустая строка,test
команда всегда завершается успешно. Чтобы фактически запустить команду, отбросьте[
команду.источник
bash
не имеет логического типа данных, и поэтому нет ключевых слов, представляющих истину и ложь.if
Оператор просто проверяет , является ли команда , которую вы дать его успех или неудачу. Командаtest
принимает выражение и успешно выполняется, если выражение истинно; непустая строка - это выражение, которое оценивается как true, как и в большинстве других языков программирования.false
это команда, которая всегда терпит неудачу. (По аналогии,true
это команда, которая всегда добивается успеха.)if [[ false ]];
тоже возвращает true. Как делаетif [[ 0 ]];
. Иif [[ /usr/bin/false ]];
не пропускает блок тоже. Как ложь или 0 могут быть оценены как ненулевые? Черт, это расстраивает. Если это имеет значение, OS X 10.8; Баш 3.false
за булеву константу или0
за целочисленный литерал; оба являются просто обычными строками.[[ x ]]
эквивалентно[[ -n x ]]
для любой строкиx
, которая не начинается с дефиса.bash
не имеет каких - либо логических констант в любом контексте. Строки, которые выглядят как целые числа, обрабатываются как таковые внутри(( ... ))
или с операторами, такими как-eq
или-lt
внутри[[ ... ]]
.if $predicate
можно легко злоупотребить для выполнения враждебного кода способом, которыйif [[ $predicate ]]
не может.Быстрый булев праймер для Bash
if
Оператор принимает команду в качестве аргумента (как&&
,||
и т.д.). Целочисленный код результата команды интерпретируется как логическое значение (0 / null = true, 1 / else = false).test
Оператор принимает операторы и операнды в качестве аргументов и возвращает код результата в том же формате, что иif
. Псевдонимtest
оператора[
, который часто используется сif
для выполнения более сложных сравнений.Операторы
true
иfalse
ничего не делают и возвращают код результата (0 и 1 соответственно). Таким образом, они могут быть использованы как логические литералы в Bash. Но если вы поместите операторы в место, где они интерпретируются как строки, вы столкнетесь с проблемами. В твоем случае:Так:
Это похоже на что-то вроде
echo '$foo'
противecho "$foo"
.При использовании
test
оператора результат зависит от используемых операторов.Короче говоря , если вы просто хотите протестировать что-то как pass / fail (иначе «true» / «false»), то передайте команду в свой оператор
if
или&&
т. Д. Без скобок. Для сложных сравнений используйте скобки с соответствующими операторами.И да, я знаю, что в Bash нет такого понятия, как родной логический тип, и что
if
и,[
иtrue
с технической точки зрения это «команды», а не «операторы»; это просто очень простое, функциональное объяснение.источник
if (( $x )); then echo "Hello"; fi
показывает сообщение для,x=1
но не дляx=0
илиx=
(не определено).Я обнаружил, что могу сделать некоторую базовую логику, запустив что-то вроде:
источник
( $A && $B )
это удивительно неэффективная операция - вы порождаете подпроцесс с помощью вызоваfork()
, затем разбиваете строку содержимого,$A
чтобы создать список элементов (в данном случае размер один), и оценивает каждый элемент как глобус (в данном случае один который оценивает себя), затем запускает результат как команду (в данном случае встроенную команду).true
иfalse
строки приходят откуда - то еще, есть риск , что они могут фактически содержать иное , чем содержаниеtrue
илиfalse
, и вы можете получить неожиданное поведение вплоть до произвольного выполнения команды.A=1; B=1
иif (( A && B ))
- обрабатывать их как числовые - или[[ $A && $B ]]
, которые рассматривают пустую строку как false и непустую строку как true.Использование true / false удаляет некоторые помехи в скобках ...
источник
[[ "$0" =~ "bash" ]]
Я изменил этот тест, чтобы скрипт работал на меня.