bash -e виходить, коли let або expr оцінюється на 0


19

У мене є bash-скрипт, який встановлює -e, щоб сценарій вийшов з будь-якого статусу виходу! = 0.

Я намагаюся виконати деяку основну арифметику оболонки, присвоєну змінним, а іноді вираз дорівнює 0, що призводить до того, що статус виходу команди let або expr буде "1".

Ось приклад:

#!/bin/bash -ex
echo "Test 1"
Z=`expr 1 - 1` || true
echo "Z will print"
let "A=4 - 4"
echo "A WILL NEVER PRINT $A"
Y=`expr 1 - 1`
echo "Y WILL NEVER PRINT $Y"
X=$(expr 2 - 2)
echo "X WILL NEVER PRINT $X"

Вихід:

$ ./test_error.sh 
+ echo 'Test 1'
Test 1
++ expr 1 - 1
+ Z=0
+ true
+ echo 'Z will print'
Z will print
+ let 'A=4 - 4'

Моє запитання - який ідіоматичний сценарій баш-сценарію, щоб дозволити сценарію виходити з ладу на реальних помилках виходу, а не на базовій арифметиці, рівній 0. Я можу суфіксувати всі ці вирази:

A=`expr $C - $D`    || true

Але це здається гакітним.

Відповіді:


16

Не використовуйте exprдля арифметики. Він давно застарів: оболонки тепер мають вбудовану арифметику, з $((…))конструкцією (POSIX), або з letвбудованим (ksh / bash / zsh) або ((…))конструкцією (ksh / bash / zsh).

letі ((…))поверніть 1 (код статусу відмови), якщо останній оцінений вираз дорівнює 0. Щоб уникнути цього не призвело до того, що ваш скрипт не закриється set -e, домовтеся, щоб останній вираз не повертав 0, наприклад:

let "a = 2 - 2" 1
((a = 2 - 2, 1))

Як варіант, використовуйте || trueідіому:

((a = 2 - 2)) || true

Як альтернативу, виконайте арифметику всередині $((…))та свої завдання зовні. Завдання повертає статус останньої підстановки команди у значенні, або 0, якщо підстановки команди немає, тож ви в безпеці. Це має додаткову перевагу роботи в будь-якій оболонці POSIX (наприклад, тире).

a=$((2 - 2))

1

Використовуйте $(( $C - $D ))замість цього арифметичний. Це теж більш ефективно.


Що робить його більш ефективним, ніж говорити (( A = $C - $D ))?
єпископ

1

У мене була така ж проблема . tl; dr:

Якщо останній ARG [від let] дорівнює 0, нехай повертається 1; нехай повертається 0 інакше.


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.