O script não sai quando a saída da função é atribuída a uma variável

0

Algumas perguntas sobre o exemplo de script abaixo.

Estou chamando uma função _foo e quero capturar a saída dela em uma variável $bar , mas também usar o status de retorno (que pode não ser 0 ou 1 ) ou, caso contrário, tem exit parar o script (quando diferente de zero).

  • Por que a exit na função _foo não funciona quando é chamada dessa maneira? (%código%). Funciona quando chamado "normalmente".
    • o if ! bar="$(_foo)" parará o script se eu alterar a instrução if para isso (mas perder sua saída): exit
    • o if ! _foo ; then se comporta como exit e não interrompe o script: return
    • Apenas chamar uma função sem a atribuição e uma saída funcionará, no entanto, chamá-la como if ! bar="$(_foo)" ; then não.
  • Existe uma maneira melhor de capturar a saída de var="$(func)" em _foo da função, bem como usar o status de retorno (diferente de $bar ou 0 , por exemplo, uma instrução 1 ?)

Tenho a sensação de que talvez precise usar case de alguma forma.

Aqui está um exemplo simples:

#!/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"

Aqui está o ooutput:

$ ./foo.sh 
start
foo failed
baz
end

Veja mais alguns exemplos:

Isso sairá:

#!/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"

Isso não sairá:

#!/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"
    
por David 07.12.2016 / 21:46

2 respostas

3

exit dentro de uma função sai do script inteiro e não apenas da função (apesar de subshell). Para expor:

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

O script acima terminará com o código de saída 3, enquanto

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

terminará com o código de saída 0.

A sintaxe $(command) que você está usando executa command dentro de uma subshell, e exit só pode ir além da camada em que a subshell está em execução .

Se você deseja capturar o código de saída e a saída de algo executado em um subshell, isso ainda está disponível para o ambiente no qual a subshell é iniciada:

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

Você também pode fazer isso de outra maneira.

_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
}

Agora chame _foo desta maneira:

$ _foo bar
1
$ echo "$bar"
baz

Quando você alterar echo para exit na definição da função, o exit sairá do script.

    
por 07.12.2016 / 23:25