나는 다른 사람들(특히 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