Errtrace e local

4

Estou usando o seguinte script:

#!/bin/bash -Eu

trap 'echo Hi' ERR

exit_failure() {
  echo "Hello, World!"
  return 1
}

sub_failure() {
  res=$(exit_failure)
}

sub_failure

Isso resulta no seguinte:

Hi
Hi

Se eu alterar sub_failure() para o seguinte, no entanto:

sub_failure() {
  local res=$(exit_failure)
}

Eu não recebo saída; ERR não está mais preso? Por que o sinal está oculto? Como posso capturar ERR se eu quiser usar variáveis locais? Eu sei que posso fazer local res; res=$(exit_failure) , mas por que eu tenho que separar os dois?

    
por implicit_knowledge 24.07.2014 / 14:10

1 resposta

4

Não é um bug. Na verdade, é um comportamento definido.

Ao usar bash -Eux , você pode ver o que acontece. ( -Eu do seu shebang + -x )

+ trap 'echo Hi' ERR
+ sub_failure
++ exit_failure
++ echo 'Hello, World!'
++ return 1
+++ echo Hi
+ res='Hello, World!
Hi'
++ echo Hi
Hi
++ echo Hi
Hi

Ao fazer a substituição do comando, o trap é herdado por causa da opção -E . Portanto, o "Hi" da interceptação herdada acionada pela função return 1 de sua função exit_failure() torna-se parte do valor armazenado em ret . (Este também é o caso ao executar a variante usando local )

Além disso, a expressão res=... retorna 1 (erro) e aciona sua interceptação (dentro de sua função sub_failure() ).

Como res=... return 1 e o resultado de uma função é o resultado do último comando na função, o resultado de sub_failure() também é 1 (error) e seu trap é acionado novamente após sub_failure foi executado no shell principal. Então você ganha 2 "Hi" s visíveis: um para res=.... e um para sub_failure e um "Hi" oculto armazenado em $res .

Agora, para a variante local :

+ trap 'echo Hi' ERR
+ sub_failure
++ exit_failure
++ echo 'Hello, World!'
++ return 1
+++ echo Hi
+ local 'res=Hello, World!
Hi'

Por definição local sempre retorna 0 quando usado em uma função. Faz com que seu local res=... avalie para 0 (sucesso) enquanto ainda tem o "Hi" oculto armazenado em $res . E como res=.. avalia para 0 sub_failure , também retorna 0 . Então desta vez você tem uma falha "oculta" e duas vezes sucesso.

Espero que isso ajude mesmo se esse segmento estiver tranquilo;)

E também deve estar claro por que dividir local res=... em

local res
res=....

restaura o comportamento da primeira variante ..? ;)

    
por 23.10.2015 / 02:22