스크립트에서 변수 할당을 위해 "${a:-b}"를 사용하세요.

스크립트에서 변수 할당을 위해 "${a:-b}"를 사용하세요.

나는 다른 사람들(특히 Red Hat)이 작성한 일부 스크립트를 살펴보았는데 그들의 변수 중 많은 부분이 VARIABLE1="${VARIABLE1:-some_val}" 다음 표기법이나 다른 변수에 대한 일부 확장을 사용하여 할당되었습니다.VARIABLE2="${VARIABLE2:-`echo $VARIABLE1`}"

값(예: )을 직접 선언하는 대신 이 표기법을 사용하는 이유는 무엇입니까 VARIABLE1=some_val?

이 표기법은 어떤 이점이 있거나 가능한 오류를 방지합니까?

:-이 문맥에 특별한 의미가 있나요?

답변1

이 기술을 사용하면 다른 변수가 비어 있거나 정의되지 않은 경우 한 변수에 값을 할당할 수 있습니다.노트:이 "다른 변수"는 동일하거나 다른 변수일 수 있습니다.

발췌

${parameter:-word}
    If parameter is unset or null, the expansion of word is substituted. 
    Otherwise, the value of parameter is substituted.

노트:${parameter-word}이 양식은 다음 에 따르면 유효합니다.배쉬 문서, 이러한 모든 확장의 경우:

콜론을 생략하면 설정되지 않은 매개변수만 테스트됩니다. 즉, 콜론이 포함된 경우 연산자는 두 가지를 모두 테스트합니다.범위존재하며 해당 값은 null이 아닙니다. 콜론이 생략되면 연산자는 존재 여부만 테스트합니다.

Bash에서 사용할 수 있는 모든 형태의 매개변수 확장의 전체 목록을 보려면 Bash Hacker의 위키에서 다음 주제를 확인하는 것이 좋습니다.매개변수 확장".

변수가 존재하지 않습니다

$ echo "$VAR1"

$ VAR1="${VAR1:-default value}"
$ echo "$VAR1"
default value

변수가 존재합니다

$ VAR1="has value"
$ echo "$VAR1"
has value

$ VAR1="${VAR1:-default value}"
$ echo "$VAR1"
has value

다른 변수를 평가하거나 기호의 기본값 섹션 내에서 명령을 실행하여 동일한 작업을 수행할 수 있습니다.

$ VAR2="has another value"
$ echo "$VAR2"
has another value
$ echo "$VAR1"

$

$ VAR1="${VAR1:-$VAR2}"
$ echo "$VAR1"
has another value

더 많은 예시

약간 다른 표기법, 즉 을 사용할 수도 있습니다 VARX=${VARX-<def. value>}.

$ echo "${VAR1-0}"
has another value
$ echo "${VAR2-0}"
has another value
$ echo "${VAR3-0}"
0

위의 $VAR1& 에서는 $VAR2"has another value"라는 문자열로 정의했지만, $VAR3정의되어 있지 않아 기본값을 사용합니다 0.

다른 예시

$ VARX="${VAR3-0}"
$ echo "$VARX"
0

:=기호 확인 및 할당 사용

마지막으로 편의 연산자인 :=. 테스트 중인 변수가 비어 있거나 정의되지 않은 경우 값을 확인하고 할당합니다.

이제 이것이 $VAR1설정되었습니다. 운영자는 :=한 번의 작업으로 테스트와 배포를 완료합니다.

$ unset VAR1
$ echo "$VAR1"

$ echo "${VAR1:=default}"
default
$ echo "$VAR1"
default

그러나 이전에 값을 설정한 경우에는 변경되지 않습니다.

$ VAR1="some value"
$ echo "${VAR1:=default}"
some value
$ echo "$VAR1"
some value

편리한 플레이보이 참조 시트

매개변수 설정 및 비어 있지 않음 매개변수가 설정되었지만 비어 있습니다. 매개변수가 설정되지 않았습니다.
${parameter:-word} 바꾸다범위 바꾸다단어 바꾸다단어
${parameter-word} 바꾸다범위 바꾸다유효하지 않은 바꾸다단어
${parameter:=word} 바꾸다범위 분배하다단어 분배하다단어
${parameter=word} 바꾸다범위 바꾸다유효하지 않은 분배하다단어
${parameter:?word} 바꾸다범위 오류, 종료 오류, 종료
${parameter?word} 바꾸다범위 바꾸다유효하지 않은 오류, 종료
${parameter:+word} 바꾸다단어 바꾸다유효하지 않은 바꾸다유효하지 않은
${parameter+word} 바꾸다단어 바꾸다단어 바꾸다유효하지 않은

(소스 테이블 스크린샷)

이것사이에는 차이가 있습니다그리고치환명시적: 할당은 변수의 값을 설정하지만 대체는 그렇지 않습니다.

인용하다

답변2

@slm 이미 포함되어 있음POSIX 문서- 이는 매우 도움이 되지만, 이러한 매개변수가 결합되어 서로 영향을 미칠 수 있는 방법을 실제로 확장하지는 않습니다. 이 양식은 여기에 언급되지 않았습니다.

${var?if unset parent shell dies and this message is output to stderr}

이것은 에서 발췌한 것입니다.또 다른 대답내 생각엔 그것이 어떻게 작동하는지 잘 보여주는 것 같아요.

    sh <<-\CMD
    _input_fn() { set -- "$@" #redundant
            echo ${*?WHERES MY DATA?}
            #echo is not necessary though
            shift #sure hope we have more than $1 parameter
            : ${*?WHERES MY DATA?} #: do nothing, gracefully
    }
    _input_fn heres some stuff
    _input_fn one #here
    # shell dies - third try doesnt run
    _input_fn you there?
    # END
    CMD
heres some stuff
one
sh: line :5 *: WHERES MY DATA?

또 다른 예는 다음과 같습니다.동일한:

    sh <<-\CMD
    N= #N is NULL
    _test=$N #_test is also NULL and
    v="something you would rather do without"    
    ( #this subshell dies
        echo "v is ${v+set}: and its value is ${v:+not NULL}"
        echo "So this ${_test:-"\$_test:="} will equal ${_test:="$v"}"
        ${_test:+${N:?so you test for it with a little nesting}}
        echo "sure wish we could do some other things"
    )
    ( #this subshell does some other things 
        unset v #to ensure it is definitely unset
        echo "But here v is ${v-unset}: ${v:+you certainly wont see this}"
        echo "So this ${_test:-"\$_test:="} will equal NULL ${_test:="$v"}"
        ${_test:+${N:?is never substituted}}
        echo "so now we can do some other things" 
    )
    #and even though we set _test and unset v in the subshell
    echo "_test is still ${_test:-"NULL"} and ${v:+"v is still $v"}"
    # END
    CMD
v is set: and its value is not NULL
So this $_test:= will equal something you would rather do without
sh: line 7: N: so you test for it with a little nesting
But here v is unset:
So this $_test:= will equal NULL
so now we can do some other things
_test is still NULL and v is still something you would rather do without

위의 예는 POSIX 매개변수 대체의 4가지 형태와 그 변형을 모두 활용합니다.:colon null또는not null시험. 위 링크에 더 많은 정보가 있고,여기 또 간다.

사람들이 종종 고려하지 않는 또 다른 사항 ${parameter:+expansion}은 여기 문서에서 그것이 얼마나 큰 역할을 하는지입니다. 여기 또 다른 발췌문이 있습니다다른 답변:

맨 위

여기서는 몇 가지 기본값을 설정하고 호출 시 인쇄되도록 준비합니다.

#!/bin/sh
    _top_of_script_pr() ( 
        IFS="$nl" ; set -f #only split at newlines and don't expand paths
        printf %s\\n ${strings}
    ) 3<<-TEMPLATES
        ${nl=
}
        ${PLACE:="your mother's house"}
        ${EVENT:="the unspeakable."}
        ${ACTION:="heroin"}
        ${RESULT:="succeed."}
        ${strings:="
            I went to ${PLACE} and saw ${EVENT}
            If you do ${ACTION} you will ${RESULT}
        "}
    #END
    TEMPLATES

가운데

결과에 따라 인쇄 기능을 호출하기 위해 여기에서 다른 기능을 정의할 수 있습니다.

    EVENT="Disney on Ice."
    _more_important_function() { #...some logic...
        [ $((1+one)) -ne 2 ] && ACTION="remedial mathematics"
            _top_of_script_pr
    }
    _less_important_function() { #...more logic...
        one=2
        : "${ACTION:="calligraphy"}"
        _top_of_script_pr
    }

맨 아래

이제 모든 설정이 완료되었으므로 여기에서 결과를 실행하고 추출해 보겠습니다.

    _less_important_function
    : "${PLACE:="the cemetery"}" 
    _more_important_function
    : "${RESULT:="regret it."}" 
    _less_important_function    

결과

이유는 나중에 설명하겠지만 위의 명령을 실행하면 다음과 같은 결과가 나타납니다.

_less_important_function()'s첫 번째 실행:

너희 엄마 집에 가서 봤어디즈니 온 아이스.

당신이 그렇게한다면달필너는 성공 할거야.

그 다음에_more_important_function():

나는 갔다묘지디즈니 온 아이스도 봤습니다.

당신이 그렇게한다면수학 과외너는 성공 할거야.

_less_important_function()다시:

묘지에 가서 디즈니 온 아이스(Disney on Ice)를 봤어요.

수학을 과외하면후회.

작동 방식:

여기서 중요한 특징은 컨셉입니다.conditional ${parameter} expansion.변수가 설정되지 않았거나 null인 경우에만 다음 형식을 사용하여 변수를 값으로 설정할 수 있습니다.

${var_name:=desired_value}

설정되지 않은 변수만 설정하려는 경우 생략할 수 있습니다.:colon그리고 null 값은 그대로 유지됩니다.

범위:

위의 예에서 알 수 있듯이$PLACE그리고$RESULT설정을 통과할 때 변경되는 내용parameter expansion하지만_top_of_script_pr()호출되었으며 아마도 런타임에 설정되었을 것입니다. 이것이 작동하는 이유는_top_of_script_pr()( subshelled )기능 - 포함합니다parens대신에{ curly braces }다른 사람들을 위해. 서브쉘에서 호출되기 때문에 설정하는 모든 변수는 다음과 같습니다.locally scoped이 값은 상위 쉘로 돌아가면 사라집니다.

하지만 때_more_important_function()세트$ACTION이것은globally scoped그래서 영향을 끼친다_less_important_function()'s두 번째 검토$ACTION왜냐하면_less_important_function()세트$ACTION오직 통해서만${parameter:=expansion}.

답변3

개인적인 경험.

나는 때때로 값을 임시로 덮어쓰기 위해 스크립트에서 이 형식을 사용합니다. 예를 들어 다음과 같은 경우가 있습니다.

$ cat script.sh
SOMETHING="${SOMETHING:-something}"; echo "$SOMETHING"; 

나는 뛸 수 있습니다:

$ env SOMETHING="something other than the default value" ./script.sh` 

변경할 필요가 없는 원래 기본값입니다 SOMETHING.

답변4

개별 명령줄 인수를 얻는 흥미로운 방법은 $1, $2... 구성표를 사용하는 것입니다.

echo "$1 $2 $3"
Two=$(2:-'default2')
echo "Second parameter: $Two"

매개변수로 호출됨: 트리에서 승리함

결과: 두 번째 매개변수: too

호출 매개변수: 5개!

결과: 두 번째 매개변수: default2

관련 정보