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
    }
    

    other_functionfunction other_function {Bourne 구문이 아닌 구문을 사용하여 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)glob 한정자 / for / (D), 대소문자를 구분하지 않는 와일드카드를 위한 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

모자 팁쿠엔람그들의shopt -q답변.

답변4

RETURN 트랩 사용

트랩으로 지정된 명령은 RETURN실행된 쉘 함수 또는 쉘 스크립트를 사용하거나 반환하기 전에 실행됩니다..source

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

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

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

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

shopt -p -o표준 상당품으로 단순화할 수 있습니다 set +o.

관련 정보