Простое утверждение if

Моя проблема может быть упрощена до выполнения следующей работы скрипта (который принимает 1 аргумент командной строки):

#!/bin/bash
if ["$1" == "0"]; then
    echo "good"
else
    echo "bad"
fi

Это должно хорошо печатать, когда я запускаю скрипт 0, но я не могу его получить. Я пробовал различные комбинации котировок вокруг чисел, и я пробовал =, == и -eq. Итак... bash, как это работает?

Ответ 1

[ самом деле это команда. Сделайте ls/bin/[ или ls/usr/bin/[. Вы увидите, что это фактически исполняемый файл.

[...] из старых дней оболочки Борна. Команда if выполняет оператор, и если код выхода этого оператора равен нулю, оператор считается истинным и выполняется условие if. Если код выхода не равен нулю, выполняется условие else (если оно присутствует).

Попробуйте эти:

$ date
Fri May 18 00:04:03 EDT 2012
echo $?   #Prints the exit code of the date command
0

$ date -Q  #Shouldn't work, I hope...
date: illegal option -- q
usage: date [-jnu] [-d dst] [-r seconds] [-t west] [-v[+|-]val[ymwdHMS]] ... 
    [-f fmt date | [[[mm]dd]HH]MM[[cc]yy][.ss]] [+format]
$ echo $?    #Exit code for the date command
1

Вы можете видеть, что эта date является допустимой командой и возвращает код выхода 0 (значение $?), Но date -Q недопустима и возвращает код выхода из 1.

Теперь попробуйте их в выражении if:

if date
then
   echo "I've successfully printed out the date!"
else
   echo "I made a mistake in the command"
fi

Теперь попробуйте следующее:

if date -q
then
   echo "I've successfully printed out the date!"
else
   echo "I made a mistake in the command"
fi

Первоначально [...] был псевдонимом для команды test. Следующие эквиваленты:

if test -f /bin/ls    #Does a file called /bin/ls exist?
then
   echo "There a /bin/ls file"
fi

а также

if [ -f /bin/ls ]
then
   echo "There a /bin/ls file"
fi

Вот почему очень важно размещать пробелы вокруг [ и ]. Потому что это на самом деле команды. В BASH встроены в оболочку, но они являются командами. Это также объясняет, почему все параметры теста (такие как -f, -z и -eq) имеют префикс тире. Они были исходными параметрами для команды test.

Ответ 2

Используйте пробел между скобкой и аргументом

$ cat x
#!/bin/bash
if [ "$1" == "0" ]; then
    echo "good"
else
    echo "bad"
fi

$ bash x 0
good

Ответ 3

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

#!/bin/bash 
if (($1 == 0)); then 
    echo "good" 
else 
    echo "bad" 
fi 

Общее правило: используйте (( )) для арифметики и [[ ]] для текста и шаблонов.
Как говорили другие, [старый синтаксис оболочки Bourne, и есть несколько причин для его использования.