unset 사용 vs. 변수를 비워두기


108

저는 현재 테스트 함수에서 표준 bash 테스트 ( [[)와 사전 정의 된 매처를 모두 사용할 수 있는 bash 테스트 프레임 워크를 작성 중 입니다. Matchers는 '[['에 대한 래퍼이며 반환 코드를 반환하는 것 외에도 예상 한 내용을 나타내는 의미있는 메시지를 설정합니다.

예:

string_equals() {
    if [[ ! $1 = $2 ]]; then
            error_message="Expected '$1' to be '$2'."

            return 1
    fi
}

따라서 matcher가 사용되어 실패하면 error_message가 설정됩니다.

이제 어느 시점에서 테스트가 성공했는지 테스트합니다. 성공하면 기대치를 녹색으로 인쇄하고 실패하면 빨간색으로 인쇄합니다.

또한 error_message 세트가있을 수 있으므로 메시지가 있는지 테스트하고 인쇄 한 다음 설정 해제합니다 (다음 테스트에서는를 설정하지 않을 수 있기 때문 error_message).

if [[ $error_message ]]; then
    printf '%s\n' "$error_message"

    unset -v error_message
fi

이제 내 질문은 변수를 설정 해제하거나 ''로 설정하는 것이 더 나은 경우입니다.

error_message=''

어느 것이 더 낫습니까? 실제로 차이가 있습니까? 아니면 메시지가 설정되었음을 나타내는 추가 플래그가 있어야합니까?


1
error_message다른 것과 비교 하지 않으면 상관 없다고 말하고 싶습니다. 그러나 나는 당신이 원한다고 생각한다 [[ $error_message ]]. 그렇지 않으면 리터럴 문자열 "error_message"가 존재하는지 테스트하고있다.
chepner

@chepner 네, 오타였습니다. 고쳤다.
helpermethod 2014 년

답변:


143

다음을 사용하지 않는 한 대부분 차이가 없습니다 set -u.

/home/user1> var=""
/home/user1> echo $var

/home/user1> set -u
/home/user1> echo $var

/home/user1> unset var
/home/user1> echo $var
-bash: var: unbound variable

따라서 실제로 변수를 테스트하는 방법에 따라 다릅니다.

다음과 같이 설정된 경우 선호하는 테스트 방법을 추가합니다.

[[ -n $var ]]  # True if the length of $var is non-zero

또는

[[ -z $var ]]  # True if zero length

43
var="설정되지 않음"이 아닙니다. 인용되지 않은 빈 문자열 일뿐입니다. 뿐만 아니라 set -u: 매개 변수 확장의 떠들썩한 파티의 다양한 형태도 해제 및 null 값을 구분할 수있는 ${foo:bar}때 "바"로 확장을 foo"때 해제하지만," foonull 인 반면, ${foo:-bar}확장되어 "foo는이 설정되지 않았거나 널 (null) 바"인 경우.
chepner

1
[[ -n $var ]]var빈 문자열로 설정 되면 false 입니다.
chepner

1
'declare -p'를 사용하여 변수 '존재'를 확인하면 var =에 'declare-var = ""'가 표시됩니다. unset을 사용하여 제거해야합니다. 물론 읽기 전용 변수이면 얻을 수 없습니다. 물론 제거하십시오. 또한 함수 내에서 var = something을 사용하는 경우 "local var = value"를 사용하면 제거에 대해 걱정할 필요가 없습니다. "declare var = value"도 로컬이기 때문에주의해야합니다. "declare -g var = value"를 사용하여 명시 적으로 전역으로 설정해야하며 선언하지 않고 "local"을 사용하여 명시 적으로 로컬로 설정해야합니다. 전역 변수는 지워지고 / 설정되지 않은 상태로만 있습니다.
osirisgothra

@osirisgothra : 지역 변수에 대한 좋은 지적. 물론 일반적으로 캡슐화되도록 함수의 모든 변수를 선언 (또는 지역화)하는 것이 가장 좋습니다.
cdarke

3
@chepner는해야한다 ${foo-bar}대신 ${foo:bar}. 자신에 대한 테스트 :unset a; echo ">${a:-foo}-${a:foo}-${a-foo}<"
비우 Chircu에게

17

언급했듯이 unset을 사용하는 것은 배열에서도 다릅니다.

$ foo=(4 5 6)

$ foo[2]=

$ echo ${#foo[*]}
3

$ unset foo[2]

$ echo ${#foo[*]}
2

2

따라서 배열 인덱스 2를 설정 해제하면 기본적으로 배열에서 해당 요소를 제거하고 배열 크기 (?)를 줄입니다.

나만의 테스트를 ..

foo=(5 6 8)
echo ${#foo[*]}
unset foo
echo ${#foo[*]}

결과적으로 ..

3
0

따라서 전체 배열을 설정 해제하면 실제로 전체 배열이 제거된다는 것을 명확히하기 위해.


0

위의 의견을 바탕으로 다음은 간단한 테스트입니다.

isunset() { [[ "${!1}" != 'x' ]] && [[ "${!1-x}" == 'x' ]] && echo 1; }
isset()   { [ -z "$(isunset "$1")" ] && echo 1; }

예:

$ unset foo; [[ $(isunset foo) ]] && echo "It's unset" || echo "It's set"
It's unset
$ foo=     ; [[ $(isunset foo) ]] && echo "It's unset" || echo "It's set"
It's set
$ foo=bar  ; [[ $(isunset foo) ]] && echo "It's unset" || echo "It's set"
It's set
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.