Сценарий не завершается, когда функция, назначенная переменной

Несколько вопросов о примерном скрипте ниже.

Я _foo функцию _foo и хочу _foo ее вывод в переменную $bar , но также использовать статус возврата (который может не быть 0 или 1 ), или если у вас есть exit остановите скрипт (когда ненулевой ).

  • Почему при вызове этого _foo функция exit _foo работает? ( if ! bar="$(_foo)" ). Он работает, когда называется «нормально».
    • exit остановит скрипт, если я изменю инструкцию if (но я потеряю его вывод): if ! _foo ; then if ! _foo ; then
    • exit ведет себя как return и не останавливает скрипт: if ! bar="$(_foo)" ; then if ! bar="$(_foo)" ; then
    • Просто вызывать функцию без назначения, и выход будет работать, но называя его, как var="$(func)" , нет.
  • Есть ли лучший способ захватить вывод _foo в $bar из функции, а также использовать статус возврата (кроме 0 или 1 , например case ?)

У меня такое чувство, что мне может понадобиться использовать trap .


Вот простой пример:

 #!/usr/bin/env bash set -e set -u set -o pipefail _foo() { local _retval echo "baz" && false _retval=$? exit ${_retval} } echo "start" if ! bar="$(_foo)" ; then echo "foo failed" else echo "foo passed" fi echo "${bar}" echo "end" 

Вот вывод:

 $ ./foo.sh start foo failed baz end 

Вот еще несколько примеров:

Это приведет к выходу:

 #!/usr/bin/env bash set -e set -u set -o pipefail func() { echo "func" exit } var='' func echo "var is ${var}" echo "did not exit" 

Это не выйдет:

 #!/usr/bin/env bash set -e set -u set -o pipefail func() { echo "func" exit } var='' var="$(func)" echo "var is ${var}" echo "did not exit" 

exit из функции выходит из всего скрипта, а не только из функции (несмотря на то, что подклассы). Изложить:

 #!/bin/bash f() { exit 3 } f exit 0 

Вышеупомянутый скрипт завершится с кодом выхода 3, тогда как

 #!/bin/bash f() { exit 3 } (f) exit 0 

завершится с кодом выхода 0.

Синтаксис $(command) вы используете, запускает command пределах подоболочки, и exit может вырваться только до уровня, на котором работает подоболочка.

Если вы хотите захватить код выхода и вывести что-то, запущенное в подоболочку, это все еще доступно для среды, в которой инициируется подсели:

 #!/bin/bash subshelloutput="$( echo "output"; exit 3 )" returnval=$? # captures subshell's exit code : more stuff follows 

Вы также можете сделать это по-другому.

 _foo () { local _retval declare -n output="$1" # $output is local (by default with declare in a func.) ## and points to $1 output="baz" && false _retval=$? echo ${_retval} # change echo to exit } 

Теперь вызовите _foo следующим образом:

 $ _foo bar 1 $ echo "$bar" baz 

Когда вы меняете echo чтобы exit в определении функции, exit выходит из сценария.