RETURN 트랩을 사용하세요

RETURN 트랩을 사용하세요

기능이 있는데 그 pipefail안에 있는 옵션을 사용하고 싶어요. 하지만 set -o pipefail스크립트의 다른 부분이 설정되지 않을 수도 있다는 우려 때문에 단순히 를 수행하고 싶지는 않습니다 pipefail. 물론 나중에 할 수도 있지만 내 기능 외부에 설정된 set +o pipefail경우 pipefail예상치 못한 동작이 발생할 수도 있습니다.

물론 가 설정된 false | true경우 종료 코드를 측정값으로 사용할 수 있지만 pipefail이는 약간 더러워 보입니다.

설정된 bash 옵션을 확인하는 더 일반적인(그리고 아마도 표준적인?) 방법이 있습니까?

답변1

이상 에서는 bash-4.4다음을 사용할 수 있습니다.

myfunction() {
  local -
  set -o someoption
  ...
}

몇 가지 참고사항:

  • 에서 복사한 것입니다 ash. 에서는 옵션 세트를 저장하는 것을 로컬로 ash만드는 것이 아이디어입니다 . 에서는 변수의 값이나 속성에 영향을 주지 않기 때문에 $-작동합니다 ( 처음에 설정을 해제한 위치와는 반대로). 그래도 특수한 경우 와 동일한 방식 으로 작동합니다 . 즉, 설정이 해제되거나 기본 동작으로 되돌아 가지 않습니다.ashashlocalbashbashash$-
  • 로 설정된 옵션만 다루고 set -o option로 설정한 옵션은 다루지 않습니다 shopt -s option( bash두 가지 옵션 세트가 있는 유일한 쉘입니다!).
  • 지역 변수와 마찬가지로 정적이 아닌 동적 범위 지정입니다. $-함수에서 반환되면 값이 복원되지만 새 설정은 함수에서 호출하는 다른 함수나 소스 스크립트에 영향을 미칩니다. 정적 범위 지정을 원하면 ksh93으로 전환하고 다음을 사용해야 합니다.

    function myfunction {
      set -o myoption
      ...
      other_function
    }
    

    Bourne 구문이 아닌 구문 other_function으로 선언된 경우에는 영향을 받지 않습니다 .function other_function {other_function()...

  • 옵션을 재설정하지 않으므로 함수는 여전히 다른 코드에서 설정한 옵션의 영향을 받을 수 있습니다. 이를 방지하려면 대신 사용하고 싶을 것입니다 zsh. 는 is zsh와 동일 하지만 잘 알려진local -set -o localoptions에뮬레이션방법장소 상에서. 예를 들어:

    myfunction() {
      emulate -L zsh
      set -o someoption
      ...
    }
    

    옵션을 추가하는 정상적인 zsh-default 옵션 세트(일부 예외는 있지만 문서 참조)로 시작합니다. 이는 ash/bash와 같은 동적 범위 지정이기도 하지만 다음을 사용하여 다른 함수를 호출할 수도 있습니다.

    emulate zsh -c 'other_function...'
    

    other_function바닐라 zsh 옵션 세트로 호출됩니다 .

    zsh에는 또한 처음부터 전역적으로 옵션을 변경하지 않도록 할 수 있는 여러 연산자가 있습니다(예: / 에 대한 (N)/ (D)glob 한정자 , 대소 문자를 구분 하지 않는 globbing을 위한 glob 연산자,nullglobdotglob(#i)${(s:x:)var}$IFS${~var}요구매개변수 확장 시 글로빙( noglob다른 Bourne 유사 쉘에서는피하다(!) 그것)...

답변2

변수는 $SHELLOPTS콜론으로 구분된 모든 설정 옵션을 보유합니다. 예를 들어 다음과 같습니다.

braceexpand:emacs:hashall:histexpand:history:interactive-comments:monitor

특정 옵션을 확인하려면 다음을 수행하면 됩니다.

# check if pipefail is set, if not set it and remember this
if [[ ! "$SHELLOPTS" =~ "pipefail" ]]; then
    set -o pipefail;
    PIPEFAIL=0;
else
    PIPEFAIL=1;
fi

# do something here

# reset pipefail, if it was not set before
if [ "$PIPEFAIL" -eq 0 ]; then
    set +o pipefail;
fi

답변3

함수 내에서 셸 옵션을 설정하고 싶지만 호출자에게 영향을 주지 않으려면 다음 두 가지 방법을 사용하세요.

옵션 1: 서브셸

함수를 서브셸 안에 넣으세요(중괄호 대신 함수 명령문을 둘러싼 괄호에 주목하세요).

function foo() (
  set -o pipefail
  echo inside foo
  shopt -o pipefail
  # ...
)

그런 다음 호출자는 파이프 실패를 설정 해제할 수 있으며 영향을 받지 않습니다.

$ shopt -o pipefail
pipefail        off
$ foo
inside foo
pipefail        on
$ shopt -o pipefail
pipefail        off

또는

옵션 2: 테스트 및 재설정

필요에 따라 옵션을 테스트하고 재설정할 수 있습니다(함수 명령문 주위에 중괄호가 있음 - 하위 쉘 없음).

function foo() {
  shopt -q -o pipefail
  local resetpipefail=$?
  set -o pipefail
  echo inside foo
  shopt -o pipefail
  # ...
  # only reset pipefail if needed
  [[ $resetpipefail -eq 1 ]] && set +o pipefail  
}

$ shopt -o pipefail
pipefail        off
$ foo
inside foo
pipefail        on
$ shopt -o pipefail
pipefail        off

모자 팁cuonglm그들의shopt -q답변.

답변4

RETURN 트랩을 사용하세요

트랩 으로 지정된 명령은 셸 함수 또는 셸 스크립트를 실행 하거나 반환한 RETURN후 실행이 다시 시작되기 전에 실행됩니다 ..source

[...] [to shopt]
옵션 -p을 사용하면 출력이 입력으로 재사용될 수 있는 형식으로 표시됩니다.

https://www.gnu.org/software/bash/manual/bash.html

foo() {
  trap "$(shopt -p -o pipefail)" RETURN
  set -o pipefail
  echo inside foo
  shopt -o pipefail
  # ...
}

시험

$ shopt -o pipefail
pipefail        off
$ foo
inside foo
pipefail        on
$ shopt -o pipefail
pipefail        off

다음 함수 템플릿은 함수가 반환될 때 set및 옵션이 모두 원래 값으로 복원되도록 하는 일반적인 경우를 처리합니다.shopt

foo() {
  trap "$(shopt -p -o; shopt -p)" RETURN # ①
  # ...
}

shopt -p -o표준에 해당하는 것으로 단순화할 수 있습니다 set +o.

관련 정보