"선언"이 함수/명령 누락으로 인해 문제를 일으키지 않습니까?

"선언"이 함수/명령 누락으로 인해 문제를 일으키지 않습니까?

요약:bash누락된 함수의 출력을 이전(즉, {const, readonly}가 아닌) 변수에 할당하려고 하면 declare"정상" 테스트를 통해 실패를 감지할 수 있습니다. 그러나 ing 시 누락된 함수의 출력을 변수에 할당하려고 하면 declare(예: make var {constant, read-only}) "정상" 테스트에서 할당이 실패하지 않을 뿐만 아니라 다음을 사용할 수도 없습니다. "normal "내장 기능으로 인해 오류가 발생합니다. 후자의 경우를 실패하게 하려면 어떻게 해야 합니까?

세부 사항:

최근에 다음 두 스크립트로 분류하려고 시도한 더 큰 스크립트 bash내에서 문제가 발생했습니다 . 기본적으로 저는 bash( )를 사용하여 TDD를 수행하고 있습니다.snark > /dev/null

  • 누락된 명령/기능이 빨리 실패하기를 원합니다.
  • 상수가 재정의되는 것을 방지하고 싶습니다.

그런데 varing을 할 때 누락된 함수의 출력을 변수에 할당할 bash수 있게 해주는 것 같습니다 . declare예를 들어 다음 스크립트(다른 이름으로 저장 /path/to/assign_at_declare.sh)...

#!/usr/bin/env bash

function foo() {
    return 0
}

# function bar() {}               # does not exist!

declare ret_val=''
declare -r MESSAGE_PREFIX="$(basename "${BASH_SOURCE}"):"
declare -r ERROR_PREFIX="${MESSAGE_PREFIX} ERROR:"

echo -e "\n${MESSAGE_PREFIX} a naïve 1st attempt:\n"

declare -ir FOO1_VAL="$(foo)"   # this should succeed, and does
ret_val="${?}"
if   [[ "${ret_val}" -ne 0  ]] ; then
    >&2 echo "${ERROR_PREFIX} foo returned '${ret_val}', exiting ..."
    exit 3
elif [[ -z "${FOO1_VAL}"  ]] ; then
    >&2 echo "${ERROR_PREFIX} foo returned null, exiting ..."
    exit 4
else
    echo "${MESSAGE_PREFIX} FOO1_VAL='${FOO1_VAL}'"
fi

declare -ir BAR1_VAL="$(bar)"   # this should fail ... but doesn't
ret_val="${?}"
if   [[ "${ret_val}" -ne 0  ]] ; then
    >&2 echo "${ERROR_PREFIX} bar returned '${ret_val}', exiting ..."
    exit 5
elif [[ -z "${BAR1_VAL}"  ]] ; then
    >&2 echo "${ERROR_PREFIX} bar returned null, exiting ..."
    exit 6
else
    echo "${MESSAGE_PREFIX} BAR1_VAL='${BAR1_VAL}'"
fi

echo -e "\n${MESSAGE_PREFIX} get tough using \`set\` builtins:\n"
# see https://www.gnu.org/software/bash/manual/html_node/The-Set-Builtin.html
set -o errexit
set -o pipefail

declare -ir FOO2_VAL="$(foo)"   # this should succeed, and does
ret_val="${?}"
if   [[ "${ret_val}" -ne 0  ]] ; then
    >&2 echo "${ERROR_PREFIX} foo returned '${ret_val}', exiting ..."
    exit 3
elif [[ -z "${FOO2_VAL}"  ]] ; then
    >&2 echo "${ERROR_PREFIX} foo returned null, exiting ..."
    exit 4
else
    echo "${MESSAGE_PREFIX} FOO2_VAL='${FOO2_VAL}'"
fi

declare -ir BAR2_VAL="$(bar)"   # this should fail ... but doesn't
ret_val="${?}"
if   [[ "${ret_val}" -ne 0  ]] ; then
    >&2 echo "${ERROR_PREFIX} bar returned '${ret_val}', exiting ..."
    exit 5
elif [[ -z "${BAR2_VAL}"  ]] ; then
    >&2 echo "${ERROR_PREFIX} bar returned null, exiting ..."
    exit 6
else
    echo "${MESSAGE_PREFIX} BAR2_VAL='${BAR2_VAL}'"
fi

exit 0

...다음과 같은 출력이 생성됩니다.

assign_at_declare.sh: a naïve 1st attempt:

assign_at_declare.sh: FOO1_VAL='0'
/path/to/assign_at_declare.sh: line 27: bar: command not found
assign_at_declare.sh: BAR1_VAL='0'

assign_at_declare.sh: get tough using `set` builtins:

assign_at_declare.sh: FOO2_VAL='0'
/path/to/assign_at_declare.sh: line 56: bar: command not found
assign_at_declare.sh: BAR2_VAL='0'

누락된 함수의 출력을 변수에 할당하려고 하면 이 동작을 관찰하지 못하기 때문에 이상해 보입니다.뒤쪽에 declareing var(즉, var가아니요{상수, 읽기 전용}) 다음 스크립트에 표시된 대로(다른 이름으로 저장 /path/to/assign_after_declare.sh)...

#!/usr/bin/env bash

function foo() {
    return 0
}

# function bar() {}           # does not exist!

declare ret_val=''
declare -i foo_val=0
declare -i bar_val=0
declare -r MESSAGE_PREFIX="$(basename "${BASH_SOURCE}"):"
declare -r ERROR_PREFIX="${MESSAGE_PREFIX} ERROR:"

echo -e "\n${MESSAGE_PREFIX} following works as expected\n"

foo_val="$(foo)"           # this should succeed, and does with/out `declare`
ret_val="${?}"
if   [[ "${ret_val}" -ne 0  ]] ; then
    >&2 echo "${ERROR_PREFIX} foo returned '${ret_val}', exiting ..."
    exit 3
elif [[ -z "${foo_val}"  ]] ; then
    >&2 echo "${ERROR_PREFIX} foo returned null, exiting ..."
    exit 4
else
    echo "${MESSAGE_PREFIX} foo_val='${foo_val}'"
fi

bar_val="$(bar)"           # this succeeds with `declare`, fails without
ret_val="${?}"
if   [[ "${ret_val}" -ne 0  ]] ; then
    >&2 echo "${ERROR_PREFIX} bar returned '${ret_val}', exiting ..."
    exit 5
elif [[ -z "${bar_val}"  ]] ; then
    >&2 echo "${ERROR_PREFIX} bar returned null, exiting ..."
    exit 6
else
    echo "${MESSAGE_PREFIX} bar_val='${bar_val}'"
fi

exit 0

...다음과 같은 출력이 생성됩니다.

assign_after_declare.sh: following works as expected

assign_after_declare.sh: foo_val='0'
/path/to/assign_after_declare.sh: line 29: bar: command not found
assign_after_declare.sh: ERROR: bar returned '127', exiting ...

bash할당 시 빠른 실패를 강제하는 방법이 있나요?기간declare? 그렇다면 귀하의 답변을 기다리겠습니다.

아니면 bash설계된 대로 작동합니까? 그렇다면 참조 링크를 연결해 주세요. 문제를 검색해 보았으나 선택기가 올바르지 않거나 관련 없는 응답을 너무 많이 반환하여 유용하지 않았습니다.

답변1

declare반품상태는:

0, 잘못된 옵션이 발견되지 않는 한 정의 함수를 사용해 보십시오. -f foo=bar읽기 전용 변수에 값을 할당해 보십시오. 복합 할당 구문을 사용하지 않고 배열 변수에 값을 할당해 보십시오. 이름 중 하나가 유효하지 않습니다. 쉘 변수 이름을 사용하려면 읽기 전용 변수에 대한 읽기 전용 상태를 끄거나, 배열 변수에 대한 배열 상태를 끄거나, -f.

이러한 경우 중 어느 것도 적용되지 않으므로 Bash는 귀하가 말한 대로 설계된 대로 작동하고 있습니다.

$(bar)bar표준 출력 없이 오류와 함께 종료되는 서브셸에서 실행됩니다 . 대체 결과는 빈 문자열이며 정수 변수의 경우 0으로 해석됩니다.declare문서에 따르면 0을 반환합니다..


할 수 있다다음을 통해 결함을 감지합니다.

declare -ir x="$(bar || echo failed running bar >&3)"

fd 3을 미리 적절하게 설정하십시오. 이러한 설정은 독자의 연습 문제로 남겨 둡니다.

관련 정보