Errtrace 및 로컬

Errtrace 및 로컬

다음 스크립트를 사용하고 있습니다.

#!/bin/bash -Eu

trap 'echo Hi' ERR

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

sub_failure() {
  res=$(exit_failure)
}

sub_failure

결과는 다음과 같습니다.

Hi
Hi

그러나 sub_failure()다음과 같이 변경하면 :

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

더 이상 출력이 나오지 ERR않습니까? 신호가 숨겨져 있는 이유는 무엇입니까? ERR지역 변수를 사용하려면 어떻게 캡처해야 합니까? 할 수 있다는 건 알지만 local res; res=$(exit_failure)왜 둘을 분리해야 합니까?

답변1

이것은 실수가 아닙니다. 이것은 실제로 정의된 동작입니다.

당신이 그것을 사용할 때 bash -Eux무슨 일이 일어나는지 볼 수 있습니다 . ( -Eu당신의 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

명령 대체를 수행할 때 스위치 trap로 인해 -E상속됩니다 . 따라서 함수 에 return 1의해 트리거된 상속 트랩의 "Hi"는 . (실행 변형을 사용할 때도 마찬가지입니다 )exit_failure()retlocal

또한 res=...표현식은 1(오류)를 반환하고 트랩( sub_failure()함수 내부)을 트리거합니다.

res=...함수의 return 및 결과 는 1함수의 마지막 명령의 결과이므로 결과 도 (error) 이며 sub_failure()메인 쉘에서 실행 1후 트랩이 다시 트리거됩니다 . sub_failure따라서 2개의 "Hi"가 표시됩니다. for res=....및 for sub_failure와 숨겨진 "Hi"가 에 저장됩니다 $res.

local이제 변형 에 대해 이야기해 보겠습니다 .

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

정의에 따르면, 함수 내에서 사용될 때 local항상 반환됩니다 . 평가 결과 도 반환되기 때문에 숨겨진 "Hi"를 저장하면서 (성공) 로 평가하게 0됩니다 . 따라서 이번에는 "숨겨진" 실패 하나와 성공 두 개를 얻게 됩니다.local res=...0$resres=..0 sub_failure0

비록 이 스레드가 오래되었지만 도움이 되기를 바랍니다. ;)

local res=...또한 우리가 분할 해야 하는 이유도 분명해야 합니다.

local res
res=....

첫 번째 변형의 동작을 복원합니다..? ;)

관련 정보