Збережіть вихідний код на потім


15

Тож у мене є невеликий сценарій для запуску деяких тестів.

javac *.java && java -ea Test
rm -f *.class

Тепер проблема з цим полягає в тому, що коли я запускаю скрипт ./test, він поверне код виходу з успіху, навіть якщо тест не вдасться, тому що rm -f *.classуспішний.

Єдиний спосіб, коли я міг би змусити його робити те, що хочу, відчуває себе некрасивим:

javac *.java && java -ea Test
test_exit_code=$?
rm -f *.class
if [ "$test_exit_code" != 0 ] ; then false; fi

Але це здається чимось поширеною проблемою - виконайте завдання, очистіть, а потім поверніть вихідний код вихідного завдання.

Який самий ідіоматичний спосіб зробити це (в основному, або просто снарядів)?

Відповіді:


5

Ви можете згорнути команди exitта rmкоманди в одну просту команду evalтипу:

java ... && java ...
eval "rm -f *.class; exit $?"

$?Значення цього шляху при переході до того exit, що йому призначається безпосередньо перед evalзапуском.


evalзавжди улюбленець шанувальників.
mikeserv

23

Я б пішов з:

javac *.java && java -ea Test
test_exit_code=$?
rm -f *.class
exit "$test_exit_code"

Навіщо стрибати, коли exitє?


Ви можете використовувати trap:

trap 'last_error_code=$?' ERR

Наприклад:

$ trap 'last_error_code=$?' ERR
$ false
$ echo $?
1
$ echo $last_error_code $?
1 0

Ага, я згоден, це краще, ніж мій оригінал. Але все ще залишається незадовільним, що я повинен явно зберігати вихідний код до змінної. Чи не існує способу "натиснути" вихідний код і "знову" повторити його пізніше?
math4tots

@ math4tots Спробуйте оновити.
muru

Отже, з вашим оновленням я повинен би ініціалізувати last_error_code до нуля, а потім повернутися в кінці, щоб у мене був ненульовий код виходу, якщо будь-яка команда видала помилку? Це крутий трюк, але для мого сценарію злому двох рядків я думаю, що я віддаю перевагу відповіді @mikeserv.
math4tots

@ math4tots Ви завжди можете це зробити exit ${last_error_code:=0}.
muru

@avip для чого? Це вже в одиничних лапках, тому змінна оцінюється лише тоді, коли викликається пастка.
муру

9

Наскільки я знаю, найближче, що баш має до try...finallyблоку з більш схожої на мову програмування (що, напевно, ви хотіли б хотіти, якби воно було доступне) - це trapконструкція, яка працює так:

trap "rm -f *.class" EXIT
javac *.java && java -ea Test

Це виконає "rm -f * .class", коли ваш сценарій завершиться. Якщо у вас є щось складніше, ви можете поставити його у функцію:

cleanup() {
    ...
}
trap cleanup EXIT
javac *.java && java -ea Test

Якщо ви настільки схильні, ви можете перетворити це на досить загальну ідіому, яка працює приблизно як try...catch...finallyблок у C. Щось подібне:

(
  trap "catch_block; exit" ERR
  trap finally_block EXIT
  # contents of try goes here
)

Зауважте, що в дужках розмежовано нижню частину оболонки; з цією конструкцією виходить тільки нижня оболонка, якщо команда не працює, а не весь сценарій. Пам'ятайте, що передплатники є дещо обчислювально дорогими, тому не використовуйте їх занадто багато (сотні). Залежно від сценарію, можливо, ви зможете досягти такого ж ефекту ефективніше, використовуючи функції оболонки trap ... RETURN, але це залежить від вас.

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