2016-12-16 6 views
0

Я делаю простые вычисления в bash, и я заметил, что вычисления bash с использованием expr возвращают , если результат вычисления равен нулю.Почему вычисления bash возвращают 1, если результат равен нулю

[email protected]:~$ expr 42 - 40 ; echo $? 
2 
0 

[email protected]:~$ expr 42 - 84 ; echo $? 
-42 
0 

[email protected]:~$ expr 42 - 42 ; echo $? 
0 
1 

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

Я делаю некоторые вычисления внутри сценария, запущенного с set -e. Каков наилучший способ учета возвращаемого значения 1? я мог бы сделать

expr $var1 - $var2 || true 

, но это также будет игнорировать другие коды выхода, чем .

+5

'человек expr': _Exit статус 0 если EXPRESSION не является ни null, ни 0, 1, если EXPRESSION имеет значение null или 0, 2, если EXPRESSION синтаксически недействительна, и 3, если произошла ошибка. Также не используйте 'expr' для арифметики, говорят, –

+2

см. также http : //unix.stackexchange.com/questions/63166/bash-e-exits-when-let-or-expr-evaluates-to-0 – Roland

+1

Я голосую, чтобы закрыть этот вопрос как вне темы, потому что на лизинге t сначала прочитайте страницу руководства. –

ответ

1

Это всего лишь сопоставление целых чисел (как булевых значений, 0 = False, 1 = True) с кодами вывода оболочки (0 = Успех,> 0 = Сбой). Обратите внимание, что «сбой» не обязательно означает, что «программа испытала ошибку и/или потерпела крах». Другие программы делают подобные вещи:

* `grep` exits with 0 if a match is made, 1 if no match is made. 
* `test` exits 0 if its condition is true, 1 if its condition is false. 

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

В оболочке такие утверждения проверяют код выхода команды, рассматривая успех как аналогичный true и failure как аналогичный false. В этом смысле expr ... не подходит для test ... -ne 0.

В обычном языке, вы пишете что-то вроде

# Python 
n = 10 
while n - 3: # short for n > 3 
    ... 

expr выполняет арифметическое, так что имеет смысл для состояния выхода, чтобы обеспечить то же самое.

n=10 
while expr "$n" - 3; do 
    ... 
done 

Обратите внимание, что вы можете обнаружить фактические ошибки, в отличие от Boolean ложность, проверяя, если статус выхода expr больше 1.

n=10 
while true; do # "Infinite" loop 
    expr "$n" - 3 
    case $? of 
     1) break ;; 
     2) echo "Error with expr" >&2; break ;; 
    esac 

    ... 
done