Bash에 변수가 설정되어 있는지 어떻게 알 수 있습니까?
예를 들어, 사용자가 함수에 첫 번째 매개변수를 제공했는지 어떻게 확인합니까?
function a { # if $1 is set ? }
질문자 :prosseek
Bash에 변수가 설정되어 있는지 어떻게 알 수 있습니까?
예를 들어, 사용자가 함수에 첫 번째 매개변수를 제공했는지 어떻게 확인합니까?
function a { # if $1 is set ? }
if [ -z ${var+x} ]; then echo "var is unset"; else echo "var is set to '$var'"; fi
여기서 ${var+x}
는 var
가 설정되지 않은 경우 아무 것도 평가하지 않고, 그렇지 않으면 x
대체하는 매개변수 확장입니다.
따옴표를 생략할 수 있습니다(그래서 "${var+x}"
대신 ${var+x}
라고 말할 수 있음) 이 구문 및 사용법은 따옴표가 필요하지 않은 것으로만 확장될 것임을 보장하기 때문에( x
(가 더 따옴표를 필요로하지 않는다, 그래서 어떤 단어 분할을 포함하지 않는), 또는 아무것도 (이 결과 [ -z ]
, 편리 것과 같은 값 (참)로 평가하는 [ -z "" ]
도 않습니다)).
그러나 따옴표를 안전하게 생략할 수 있고 모든 사람에게 즉시 명확하지 않은 동안( 이 따옴표 설명의 첫 번째 작성자이자 주요 Bash 코더이기도 함) 때로는 솔루션을 작성하는 것이 더 나을 것입니다. 따옴표로 [ -z "${var+x}" ]
, O(1) 속도 패널티의 가능한 아주 작은 비용으로. 첫 번째 작성자는 이 답변에 대한 URL을 제공하는 이 솔루션을 사용하여 코드 옆에 주석으로 이것을 추가했습니다. 이제 따옴표를 안전하게 생략할 수 있는 이유에 대한 설명도 포함됩니다.
if [ -z "$var" ]; then echo "var is blank"; else echo "var is set to '$var'"; fi
이것은 설정되지 않은 변수와 빈 문자열로 설정된 변수를 구별하지 못하기 때문에 종종 잘못된 것입니다. 즉, var=''
이면 위의 솔루션은 "var is blank"를 출력합니다.
설정되지 않은 것과 "빈 문자열로 설정" 사이의 구별은 사용자가 확장 또는 추가 속성 목록을 지정해야 하는 상황에서 필수적이며, 이를 지정하지 않으면 기본값이 비어 있지 않은 값인 반면, 빈 문자열을 지정하면 스크립트가 빈 확장 또는 추가 속성 목록을 사용하도록 합니다.
모든 시나리오에서 구분이 필수적인 것은 아닙니다. 그런 경우에는 [ -z "$var" ]
괜찮을 것입니다.
null이 아닌/0이 아닌 문자열 변수를 확인하려면, 즉 설정된 경우 다음을 사용하십시오.
if [ -n "$1" ]
-z
의 반대입니다. -z
-n
더 많이 사용하고 있습니다.
다음과 같이 사용합니다.
if [ -n "$1" ]; then echo "You supplied the first parameter!" else echo "First parameter not supplied." fi
다음은 매개변수가 설정되지 않았는지, 비어 있는지("Null") 또는 값으로 설정 되었는지 테스트하는 방법입니다.
+--------------------+----------------------+-----------------+-----------------+ | Expression | parameter | parameter | parameter | | in script: | Set and Not Null | Set But Null | Unset | +--------------------+----------------------+-----------------+-----------------+ | ${parameter:-word} | substitute parameter | substitute word | substitute word | | ${parameter-word} | substitute parameter | substitute null | substitute word | | ${parameter:=word} | substitute parameter | assign word | assign word | | ${parameter=word} | substitute parameter | substitute null | assign word | | ${parameter:?word} | substitute parameter | error, exit | error, exit | | ${parameter?word} | substitute parameter | substitute null | error, exit | | ${parameter:+word} | substitute word | substitute null | substitute null | | ${parameter+word} | substitute word | substitute word | substitute null | +--------------------+----------------------+-----------------+-----------------+
출처: POSIX: 매개변수 확장 :
"대체"로 표시된 모든 경우에 표현식은 표시된 값으로 대체됩니다. "할당"으로 표시된 모든 경우에 매개변수에 해당 값이 지정되며 이 값도 표현식을 대체합니다.
이를 실제로 표시하려면 다음을 수행합니다.
+--------------------+----------------------+-----------------+-----------------+ | Expression | FOO="world" | FOO="" | unset FOO | | in script: | (Set and Not Null) | (Set But Null) | (Unset) | +--------------------+----------------------+-----------------+-----------------+ | ${FOO:-hello} | world | hello | hello | | ${FOO-hello} | world | "" | hello | | ${FOO:=hello} | world | FOO=hello | FOO=hello | | ${FOO=hello} | world | "" | FOO=hello | | ${FOO:?hello} | world | error, exit | error, exit | | ${FOO?hello} | world | "" | error, exit | | ${FOO:+hello} | hello | "" | "" | | ${FOO+hello} | hello | hello | "" | +--------------------+----------------------+-----------------+-----------------+
여기에 언급된 대부분의 기술이 정확하지만 bash 4.2 는 변수 값을 테스트하는 대신 변수( man bash )의 존재에 대한 실제 테스트를 지원합니다.
[[ -v foo ]]; echo $? # 1 foo=bar [[ -v foo ]]; echo $? # 0 foo="" [[ -v foo ]]; echo $? # 0
[ -z
를 사용하는 것과 같은 다른 접근 방식과 달리 set -u
/ set -o nounset
모드에서 설정되지 않은 변수를 확인하는 데 사용할 때 오류를 일으키지 않습니다.
다음과 같은 여러 가지 방법이 있습니다.
if [ -z "$1" ]
$1이 null이거나 설정되지 않은 경우 성공합니다.
나는 항상 다른 답변 에서 POSIX 테이블이 느리다는 것을 알았으므로 여기에 내 의견이 있습니다.
+----------------------+------------+-----------------------+-----------------------+ | if VARIABLE is: | set | empty | unset | +----------------------+------------+-----------------------+-----------------------+ - | ${VARIABLE-default} | $VARIABLE | "" | "default" | = | ${VARIABLE=default} | $VARIABLE | "" | $(VARIABLE="default") | ? | ${VARIABLE?default} | $VARIABLE | "" | exit 127 | + | ${VARIABLE+default} | "default" | "default" | "" | +----------------------+------------+-----------------------+-----------------------+ :- | ${VARIABLE:-default} | $VARIABLE | "default" | "default" | := | ${VARIABLE:=default} | $VARIABLE | $(VARIABLE="default") | $(VARIABLE="default") | :? | ${VARIABLE:?default} | $VARIABLE | exit 127 | exit 127 | :+ | ${VARIABLE:+default} | "default" | "" | "" | +----------------------+------------+-----------------------+-----------------------+
다릅니다가 비어있는 경우의 처리 방법이다 유일한 있도록 각 그룹 (와 콜론을 이전하지 않고), 동일한 설정 및 해제의 경우를 가지고 있습니다.
앞의 콜론을 사용하면 비어 있는 케이스와 설정되지 않은 케이스가 동일하므로 가능한 경우를 사용합니다(즉, 빈 케이스가 일치하지 않기 때문에 =
뿐만 아니라 :=
제목:
VARIABLE
이 비어 있지 않음을 의미합니다 VARIABLE="something"
).VARIABLE
이 비어 있음/널( VARIABLE=""
)임을 의미합니다.VARIABLE
이 존재하지 않음을 unset VARIABLE
)값:
$VARIABLE
은 결과가 변수의 원래 값임을 의미합니다."default"
은 결과가 제공된 대체 문자열임을 의미합니다.""
는 결과가 null(빈 문자열)임을 의미합니다.exit 127
은 스크립트가 종료 코드 127과 함께 실행을 중지함을 의미합니다.$(VARIABLE="default")
는 결과가 "default"
이고 VARIABLE
(이전에는 비어 있거나 설정되지 않음)도 "default"
과 동일하게 설정됨을 의미합니다.변수가 비어 있지 않은지 확인하려면 다음을 사용합니다.
if [[ $var ]]; then ... # `$var' expands to a nonempty string
반대는 변수가 설정되지 않았거나 비어 있는지 테스트합니다.
if [[ ! $var ]]; then ... # `$var' expands to the empty string (set or not)
변수가 설정되었는지(비어 있는지 또는 비어 있지 않은지) 확인하려면 다음을 사용합니다.
if [[ ${var+x} ]]; then ... # `var' exists (empty or nonempty) if [[ ${1+x} ]]; then ... # Parameter 1 exists (empty or nonempty)
변수가 설정되지 않은 경우 반대 테스트:
if [[ ! ${var+x} ]]; then ... # `var' is not set at all if [[ ! ${1+x} ]]; then ... # We were called with no arguments
Bash의 최신 버전(4.2 이상이라고 생각합니다. 확실하지 않음)에서 다음을 시도합니다.
if [ ! -v SOMEVARIABLE ] #note the lack of a $ sigil then echo "Variable is unset" elif [ -z "$SOMEVARIABLE" ] then echo "Variable is set to an empty string" else echo "Variable is set to some string" fi
bash
태그 때문에 Bash 중심의 답변을 하고 있습니다.
Bash에서 명명된 변수만 처리하는 한 이 함수는 변수가 설정되었는지 여부를 항상 알려주어야 합니다. 변수가 빈 배열인 경우에도 마찬가지입니다.
variable-is-set() { declare -p "$1" &>/dev/null }
Bash에서(최소한 3.0까지), var
가 선언/설정 변수인 경우 declare -p var
는 변수 var
를 현재 유형 및 값으로 설정하고 상태 코드 0
declare
명령을 출력합니다( 성공). var
가 선언되지 않은 경우 declare -p var
stderr
오류 메시지를 출력하고 상태 코드 1
반환합니다. 사용 &>/dev/null
, 모두 일반 리디렉션 stdout
과 stderr
출력하기 /dev/null
, 보지, 및 상태 코드를 변경하지 않고 할 수 않았다. 따라서 함수는 상태 코드만 반환합니다.
[ -n "$var" ]
:${var[0]}
이 비어 있지 않은지 여부만 확인합니다. (Bash에서$var
${var[0]}
과 동일합니다.)[ -n "${var+x}" ]
:${var[0]}
이 설정되어 있는지만 확인합니다.[ "${#var[@]}" != 0 ]
:$var
인덱스가 하나 이상 설정되어 있는지만 확인합니다.
이것은 단지 (포함라는 이름의 변수를 작동 $_
)이 아닌 특수한 변수 ( $!
, $@
, $#
, $$
, $*
, $?
, $-
, $0
, $1
, $2
, ..., 및 잊었을 수도 있음). 이들 중 어느 것도 배열이 아니므로 POSIX 스타일 [ -n "${var+x}" ]
은 이러한 모든 특수 변수에 대해 작동합니다. 그러나 많은 특수 변수가 함수가 호출될 때 값/존재를 변경하므로 함수로 래핑하는 것에 주의하십시오.
스크립트에 배열이 있고 가능한 한 많은 쉘과 호환되도록 하려는 경우 declare -p
대신 typeset -p
사용을 고려하십시오. 나는 ksh가 전자만 지원한다는 것을 읽었지만 이것을 테스트할 수는 없었습니다. 나는 Bash 3.0+와 Zsh 5.5.1이 각각 typeset -p
와 declare -p
모두 지원한다는 것을 알고 있습니다. 그러나 나는 그 두 키워드 이외의 차이점을 테스트하지 않았고 다른 쉘을 테스트하지 않았습니다.
스크립트가 POSIX sh와 호환되어야 하는 경우 배열을 사용할 수 없습니다. 배열이 없으면 [ -n "{$var+x}" ]
작동합니다.
이 함수는 변수 var
eval
var
eval
d 코드에 의해 설정되었는지 확인하기 위해 테스트를 실행하고, 마지막으로 다른 테스트에 대한 결과 상태 코드를 표시합니다.
test -v var
, [ -v var ]
및 [[ -v var ]]
[ -n "${var+x}" ]
과 동일한 결과를 산출하기 때문에 건너뛰고 Bash 4.2 이상이 필요합니다. . 또한 내가 테스트한 셸(Bash 3.0 ~ 5.0 및 Zsh 5.5.1)에서 declare -p
와 동일하기 때문에 typeset -p
건너뜁니다.
is-var-set-after() { # Set var by passed expression. unset var eval "$1" # Run the tests, in increasing order of accuracy. [ -n "$var" ] # (index 0 of) var is nonempty nonempty=$? [ -n "${var+x}" ] # (index 0 of) var is set, maybe empty plus=$? [ "${#var[@]}" != 0 ] # var has at least one index set, maybe empty count=$? declare -p var &>/dev/null # var has been declared (any type) declared=$? # Show test results. printf '%30s: %2s %2s %2s %2s\n' "$1" $nonempty $plus $count $declared }
변수가 연관 배열로 선언되지 않은 경우 Bash가 숫자가 아닌 배열 인덱스를 "0"으로 처리하기 때문에 테스트 결과가 예기치 않을 수 있습니다. 또한 연관 배열은 Bash 4.0 이상에서만 유효합니다.
# Header. printf '%30s: %2s %2s %2s %2s\n' "test" '-n' '+x' '#@' '-p' # First 5 tests: Equivalent to setting 'var=foo' because index 0 of an # indexed array is also the nonindexed value, and non-numerical # indices in an array not declared as associative are the same as # index 0. is-var-set-after "var=foo" # 0 0 0 0 is-var-set-after "var=(foo)" # 0 0 0 0 is-var-set-after "var=([0]=foo)" # 0 0 0 0 is-var-set-after "var=([x]=foo)" # 0 0 0 0 is-var-set-after "var=([y]=bar [x]=foo)" # 0 0 0 0 # '[ -n "$var" ]' fails when var is empty. is-var-set-after "var=''" # 1 0 0 0 is-var-set-after "var=([0]='')" # 1 0 0 0 # Indices other than 0 are not detected by '[ -n "$var" ]' or by # '[ -n "${var+x}" ]'. is-var-set-after "var=([1]='')" # 1 1 0 0 is-var-set-after "var=([1]=foo)" # 1 1 0 0 is-var-set-after "declare -A var; var=([x]=foo)" # 1 1 0 0 # Empty arrays are only detected by 'declare -p'. is-var-set-after "var=()" # 1 1 1 0 is-var-set-after "declare -a var" # 1 1 1 0 is-var-set-after "declare -A var" # 1 1 1 0 # If 'var' is unset, then it even fails the 'declare -p var' test. is-var-set-after "unset var" # 1 1 1 1
헤더 행의 테스트 니모닉은 [ -n "$var" ]
, [ -n "${var+x}" ]
, [ "${#var[@]}" != 0 ]
및 다음을 declare -p var
, 각각.
test: -n +x #@ -p var=foo: 0 0 0 0 var=(foo): 0 0 0 0 var=([0]=foo): 0 0 0 0 var=([x]=foo): 0 0 0 0 var=([y]=bar [x]=foo): 0 0 0 0 var='': 1 0 0 0 var=([0]=''): 1 0 0 0 var=([1]=''): 1 1 0 0 var=([1]=foo): 1 1 0 0 declare -A var; var=([x]=foo): 1 1 0 0 var=(): 1 1 1 0 declare -a var: 1 1 1 0 declare -A var: 1 1 1 0 unset var: 1 1 1 1
declare -p var &>/dev/null
은 (100%?) Bash에서 명명된 변수를 테스트하는 데 최소 3.0부터 신뢰할 수 있습니다.[ -n "${var+x}" ]
는 POSIX 호환 상황에서 안정적이지만 배열을 처리할 수 없습니다.- 변수가 비어 있지 않은지 확인하고 다른 쉘에서 선언된 변수를 확인하기 위한 다른 테스트가 있습니다. 그러나 이러한 테스트는 Bash나 POSIX 스크립트에 적합하지 않습니다.
if [ "$1" != "" ]; then echo \$1 is set else echo \$1 is not set fi
인수의 경우 일반적으로 인수의 수인 $#을 테스트하는 것이 가장 좋습니다.
if [ $# -gt 0 ]; then echo \$1 is set else echo \$1 is not set fi
set -u
가 있는 스크립트에서 설정되지 않았거나 비어 있는지 확인하려는 경우:
if [ -z "${var-}" ]; then echo "Must provide var environment variable. Exiting...." exit 1 fi
일반 [ -z "$var" ]
검사는 var; unbound variable
의 경우 set -u
하지만 [ -z "${var-}" ]
가 확장 빈 문자열 경우 var
실패없이 해제합니다.
이것은 나를 위해 일했습니다. 매개변수가 설정되지 않은 경우 스크립트가 오류 메시지와 함께 종료되기를 원했습니다.
#!/usr/bin/env bash set -o errexit # Get the value and empty validation check all in one VER="${1:?You must pass a version of the format 0.0.0 as the only argument}"
이것은 실행될 때 오류와 함께 반환됩니다.
peek@peek:~$ ./setver.sh ./setver.sh: line 13: 1: You must pass a version of the format 0.0.0 as the only argument
값이 set=VALID 또는 unset/empty=INVALID인지 확인하려는 경우 이 옵션을 시도하십시오.
TSET="good val" TEMPTY="" unset TUNSET if [ "${TSET:-}" ]; then echo "VALID"; else echo "INVALID";fi # VALID if [ "${TEMPTY:-}" ]; then echo "VALID"; else echo "INVALID";fi # INVALID if [ "${TUNSET:-}" ]; then echo "VALID"; else echo "INVALID";fi # INVALID
또는 짧은 테스트라도 ;-)
[ "${TSET:-}" ] && echo "VALID" || echo "INVALID" [ "${TEMPTY:-}" ] && echo "VALID" || echo "INVALID" [ "${TUNSET:-}" ] && echo "VALID" || echo "INVALID"
그리고 이것은 질문에 대한 답변입니다. 값이 set/empty=VALID 또는 unset=INVALID인지 확인하려는 경우 사용합니다.
참고, "..-1}"의 "1"은 중요하지 않으며 (x와 같은) 무엇이든 될 수 있습니다.
TSET="good val" TEMPTY="" unset TUNSET if [ "${TSET+1}" ]; then echo "VALID"; else echo "INVALID";fi # VALID if [ "${TEMPTY+1}" ]; then echo "VALID"; else echo "INVALID";fi # VALID if [ "${TUNSET+1}" ]; then echo "VALID"; else echo "INVALID";fi # INVALID
짧은 테스트
[ "${TSET+1}" ] && echo "VALID" || echo "INVALID" [ "${TEMPTY+1}" ] && echo "VALID" || echo "INVALID" [ "${TUNSET+1}" ] && echo "VALID" || echo "INVALID"
이 질문에 대한 정확한 답변을 요청한 @mklement0(댓글)에게 이 답변을 바칩니다.
참조 http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_02
bash
매뉴얼 페이지의 "매개변수 확장" 섹션을 읽으십시오. 매개변수 확장은 설정되는 변수에 대한 일반적인 테스트를 제공하지 않지만 설정되지 않은 경우 매개변수에 대해 수행할 수 있는 몇 가지 작업이 있습니다.
예를 들어:
function a { first_arg=${1-foo} # rest of the function }
first_arg
를 $1
설정하고 그렇지 않으면 "foo" 값을 사용합니다. 경우 a
절대적으로 하나의 매개 변수를 사용해야하고 좋은 기본이 존재하지 않는 매개 변수가 지정되지 않은 경우, 오류 메시지와 함께 종료 할 수 있습니다 :
function a { : ${1?a must take a single argument} # rest of the function }
(:를 null 명령으로 사용하는 것에 주의하세요 :
명령은 인수 값을 확장합니다. $1
로 아무 것도 하고 싶지 않습니다. 설정되지 않은 경우 종료하십시오.)
변수가 비어 있지 않은 값으로 설정되었는지 확인하려면 다른 사람들이 이미 표시한 것처럼 [ -n "$x" ]
대부분의 경우 값이 비어 있는 변수를 설정되지 않은 변수와 같은 방식으로 처리하는 것이 좋습니다. 그러나 다음과 같은 경우에는 둘을 구분할 수 있습니다. [ -n "${x+set}" ]
( "${x+set}"
x
가 설정된 경우 set
확장되고 x
가 설정되지 않은 경우 빈 문자열로 확장됩니다.)
매개변수가 전달되었는지 확인하려면 함수(또는 함수에 없는 경우 스크립트)에 전달된 매개변수의 수인 $#
테스트하십시오( Paul의 답변 참조).
[[ ]]
내장 내에서 -v
를 사용할 수 있습니다.
#! /bin/bash -u if [[ ! -v SOMEVAR ]]; then SOMEVAR='hello' fi echo $SOMEVAR
test -n "${var-}"
을 사용하여 변수가 비어 있지 않은지 확인합니다(따라서 정의/설정해야 함). 용법:
if test -n "${name-}"; then echo "name is set to $name" else echo "name is not set or empty" fi
test ! -z "${var+}"
사용하세요! test ! -z "${var+}"
변수가 정의/설정되었는지 확인합니다(비어 있더라도). 용법:
if test ! -z "${var+}"; then echo "name is set to $name" else echo "name is not set" fi
첫 번째 사용 사례는 셸 스크립트에서 훨씬 더 일반적이며 이것이 일반적으로 사용하려는 것입니다.
이 솔루션이 작동하는 방식을 이해하려면 POSIX test
명령 과 POSIX 셸 매개변수 확장( spec )을 이해해야 하므로 답을 이해하는 데 필요한 절대적인 기본 사항을 살펴보겠습니다.
test 명령은 표현식을 평가하고 (종료 상태를 통해) true 또는 false를 반환합니다. 연산자 -n
은 피연산자가 비어 있지 않은 문자열인 경우 true를 반환합니다. 예를 들어 test -n "a"
는 true를 반환하고 test -n ""
은 false를 반환합니다. 이제 변수가 비어 있지 않은지(즉, 정의해야 함) 확인하려면 test -n "$var"
사용할 수 있습니다. 그러나 일부 쉘 스크립트에는 정의되지 않은 변수에 대한 참조가 오류를 발생 set -u
var
가 정의되지 않은 경우 표현식 $a
는 오류를 발생시킵니다. 이 경우를 올바르게 처리하려면 변수 확장을 사용해야 합니다. 이는 변수가 정의되지 않은 경우 변수를 대체 문자열로 바꾸도록 쉘에 지시하여 앞서 언급한 오류를 방지합니다.
변수 확장 ${var-}
은 var
변수가 정의되지 않은 경우("unset"이라고도 함), 이를 빈 문자열로 대체함을 의미합니다. 따라서 test -n "${var-}"
$var
가 비어 있지 않으면 true를 반환하며, 이는 거의 항상 쉘 스크립트에서 확인하려는 것입니다. $var
가 정의되지 않았거나 비어 있지 않은 경우 역 검사 test -z "${var-}"
입니다.
이제 두 번째 사용 사례: 비어 있는지 여부에 관계없이 var
이것은 덜 일반적인 사용 사례이며 약간 더 복잡하며 더 잘 이해하려면 Lionels의 훌륭한 답변을 읽는 것이 좋습니다.
[[ -z "$var" ]]
를 사용하는 것이 변수가 설정되었는지 여부를 알 수 있는 가장 쉬운 방법이지만 -z
옵션은 설정되지 않은 변수와 빈 문자열로 설정된 변수를 구분하지 않습니다.
$ set='' $ [[ -z "$set" ]] && echo "Set" || echo "Unset" Unset $ [[ -z "$unset" ]] && echo "Set" || echo "Unset" Unset
변수의 종류(env 변수, 매개변수 또는 일반 변수)에 따라 확인하는 것이 가장 좋습니다.
환경 변수의 경우:
[[ $(env | grep "varname=" | wc -l) -eq 1 ]] && echo "Set" || echo "Unset"
매개변수의 경우(예 $5
존재 확인):
[[ $# -ge 5 ]] && echo "Set" || echo "Unset"
일반 변수의 경우(보조 기능을 사용하여 우아한 방식으로 수행):
function declare_var { declare -p "$1" &> /dev/null } declare_var "var_name" && echo "Set" || echo "Unset"
노트:
$#
: 위치 매개변수의 수를 제공합니다.declare -p
: 매개변수로 전달된 변수의 정의를 제공합니다. 존재하면 0을 반환하고, 없으면 1을 반환하고 오류 메시지를 인쇄합니다.&> /dev/null
: 반환 코드에 영향을 주지 않고declare -p
출력을 억제합니다.
변수 설정 여부를 결정하는 방법에 대한 OP의 질문에 명확하게 대답하기 위해 @Lionel의 대답은 정확합니다.
if test "${name+x}"; then echo 'name is set' else echo 'name is not set' fi
이 질문에는 이미 많은 답변이 있지만 그 중 어느 것도 변수 값을 명확하게 구별하기 위해 진정한 부울 표현식을 제공하지 않았습니다.
다음은 내가 작업한 몇 가지 명확한 표현입니다.
+-----------------------+-------------+---------+------------+ | Expression in script | name='fish' | name='' | unset name | +-----------------------+-------------+---------+------------+ | test "$name" | TRUE | f | f | | test -n "$name" | TRUE | f | f | | test ! -z "$name" | TRUE | f | f | | test ! "${name-x}" | f | TRUE | f | | test ! "${name+x}" | f | f | TRUE | +-----------------------+-------------+---------+------------+
그건 그렇고, 다음 표현식은 동일합니다. test <expression>
<=> [ <expression> ]
주의해서 사용해야 할 기타 모호한 표현:
+----------------------+-------------+---------+------------+ | Expression in script | name='fish' | name='' | unset name | +----------------------+-------------+---------+------------+ | test "${name+x}" | TRUE | TRUE | f | | test "${name-x}" | TRUE | f | TRUE | | test -z "$name" | f | TRUE | TRUE | | test ! "$name" | f | TRUE | TRUE | | test ! -n "$name" | f | TRUE | TRUE | | test "$name" = '' | f | TRUE | TRUE | +----------------------+-------------+---------+------------+
나는 아무도 grok table 을 악명 높게 생성하기 위해 프로그래밍 방식으로 쉘 스크립트를 작성하려고 시도하지 않았다는 사실에 놀랐습니다. 우리는 여기에서 코딩 기술을 배우려고 하므로 코드로 답을 표현하지 않겠습니까? :) 여기 내 의견이 있습니다 (모든 POSIX 셸에서 작동해야 함).
H="+-%s-+-%s----+-%s----+-%s--+\n" # table divider printf format R="| %-10s | %-10s | %-10s | %-10s |\n" # table row printf format S='V' # S is a variable that is set-and-not-null N='' # N is a variable that is set-but-null (empty "") unset U # U is a variable that is unset printf "$H" "----------" "-------" "-------" "---------"; printf "$R" "expression" "FOO='V'" "FOO='' " "unset FOO"; printf "$H" "----------" "-------" "-------" "---------"; printf "$R" "\${FOO:-x}" "${S:-x}" "${N:-x}" "${U:-x} "; S='V';N='';unset U printf "$R" "\${FOO-x} " "${Sx} " "${Nx} " "${Ux} "; S='V';N='';unset U printf "$R" "\${FOO:=x}" "${S:=x}" "${N:=x}" "${U:=x} "; S='V';N='';unset U printf "$R" "\${FOO=x} " "${S=x} " "${N=x} " "${U=x} "; S='V';N='';unset U printf "$R" "\${FOO:?x}" "${S:?x}" "<error>" "<error> "; S='V';N='';unset U printf "$R" "\${FOO?x} " "${S?x} " "${N?x} " "<error> "; S='V';N='';unset U printf "$R" "\${FOO:+x}" "${S:+x}" "${N:+x}" "${U:+x} "; S='V';N='';unset U printf "$R" "\${FOO+x} " "${S+x} " "${N+x} " "${U+x} "; S='V';N='';unset U printf "$H" "----------" "-------" "-------" "---------"; # For reference, the following two lines are the literal rows of the table # which would cause the script to exit and so have had <error> written in. #printf "$R" "\${FOO:?x}" "${S:?x}" "${N:?x}" "${U:?x} "; S='V';N='';unset U #printf "$R" "\${FOO?x} " "${S?x} " "${N?x} " "${U?x} "; S='V';N='';unset U
스크립트 실행 결과:
+------------+------------+------------+------------+ | expression | FOO='V' | FOO='' | unset FOO | +------------+------------+------------+------------+ | ${FOO:-x} | V | x | x | | ${FOO-x} | V | | x | | ${FOO:=x} | V | x | x | | ${FOO=x} | V | | x | | ${FOO:?x} | V | <error> | <error> | | ${FOO?x} | V | | <error> | | ${FOO:+x} | x | | | | ${FOO+x} | x | x | | +------------+------------+------------+------------+
스크립트에는 부작용 할당이 발생하거나 발생하지 않을 때 표시하는 것과 같은 몇 가지 기능이 없지만, 다른 더 야심찬 사람이 이 시작점을 잡고 실행하기를 원할 수 있습니다.
넌 할 수있어:
function a { if [ ! -z "$1" ]; then echo '$1 is set' fi }
위의 답변은 Bash 옵션 set -u
가 활성화된 경우 작동하지 않습니다. 또한 동적이 아닙니다. 예를 들어 테스트 방법이 "dummy"라는 이름의 변수가 정의되어 있습니까? 이 시도:
is_var_defined() { if [ $# -ne 1 ] then echo "Expected exactly one argument: variable name as string, eg, 'my_var'" exit 1 fi # Tricky. Since Bash option 'set -u' may be enabled, we cannot directly test if a variable # is defined with this construct: [ ! -z "$var" ]. Instead, we must use default value # substitution with this construct: [ ! -z "${var:-}" ]. Normally, a default value follows the # operator ':-', but here we leave it blank for empty (null) string. Finally, we need to # substitute the text from $1 as 'var'. This is not allowed directly in Bash with this # construct: [ ! -z "${$1:-}" ]. We need to use indirection with eval operator. # Example: $1="var" # Expansion for eval operator: "[ ! -z \${$1:-} ]" -> "[ ! -z \${var:-} ]" # Code execute: [ ! -z ${var:-} ] eval "[ ! -z \${$1:-} ]" return $? # Pedantic. }
내가 선호하는 방법은 다음과 같습니다.
$ var=10 $ if ! ${var+false};then echo "is set";else echo "NOT set";fi is set $ unset -v var $ if ! ${var+false};then echo "is set";else echo "NOT set";fi NOT set
따라서 기본적으로 변수가 설정되면 "결과 false
의 부정"이 됩니다(무엇이 true
가 될지 = "설정됨").
그리고 설정되지 않은 true
"결과 true의 부정"(빈 결과가 true
평가됨)이 됩니다(따라서 false
= "NOT set"으로 종료됨).
이것은 내가 매일 사용하는 것입니다.
# # Check if a variable is set # param1 name of the variable # function is_set() { [[ $(eval echo "\${${1}+x}") ]]; }
이것은 Linux 및 Solaris에서 bash 3.0까지 잘 작동합니다.
bash-3.00$ myvar="TEST" bash-3.00$ is_set myvar ; echo $? 0 bash-3.00$ myvar= bash-3.00$ is_set myvar ; echo $? 0 bash-3.00$ unset myvar bash-3.00$ is_set myvar ; echo $? 1
[[ $foo ]]
또는
(( ${#foo} ))
또는
let ${#foo}
또는
declare -p foo
쉘에서 문자열 길이가 0이면 True인 -z
연산자를 사용할 수 있습니다.
MY_VAR
이 설정되지 않은 경우 기본 MY_VAR을 설정하는 간단한 한 줄로, 그렇지 않으면 선택적으로 메시지를 표시할 수 있습니다.
[[ -z "$MY_VAR" ]] && MY_VAR="default" [[ -z "$MY_VAR" ]] && MY_VAR="default" || echo "Variable already set."
var
가 설정되었는지 테스트하려면 [ ${var+x} ]
.
변수가 이름으로 설정되었는지 테스트하려면 [ ${!name+x} ]
.
위치 매개변수가 설정되었는지 테스트하려면 [ ${N+x} ]
, 여기서 N은 실제로 정수입니다.
이 답변은 Lionel의 답변과 거의 유사하지만 -z
를 생략하여 보다 미니멀한 방식을 탐색합니다.
명명된 변수가 설정되었는지 테스트하려면 다음을 수행합니다.
function is_set { local v=$1 echo -n "${v}" if [ ${!v+x} ]; then echo " = '${!v}'" else echo " is unset" fi }
위치 매개변수가 설정되었는지 테스트하려면:
function a { if [ ${1+x} ]; then local arg=$1 echo "a '${arg}'" else echo "a: arg is unset" fi }
테스트는 공백과 유효한 테스트 표현식에 대한 추가 주의가 필요하지 않음을 보여줍니다.
set -eu V1=a V2= V4=-gt V5="1 -gt 2" V6="! -z 1" V7='$(exit 1)' is_set V1 is_set V2 is_set V3 is_set V4 is_set V5 is_set V6 is_set V7 a 1 a a "1 -gt 2" a 1 -gt 2
$./test.sh V1 = 'a' V2 = '' V3 is unset V4 = '-gt' V5 = '1 -gt 2' V6 = '! -z 1' V7 = '$(exit 1)' a '1' a: arg is unset a '1 -gt 2' a '1'
마지막으로 변수 이름의 오타와 같은 일반적인 오류로부터 우리를 보호 set -eu
사용을 권장하지만 이는 설정되지 않은 변수와 빈 문자열로 설정된 변수의 차이가 올바르게 처리됨을 의미합니다.
if [[ ${1:+isset} ]] then echo "It was set and not null." >&2 else echo "It was not set or it was null." >&2 fi if [[ ${1+isset} ]] then echo "It was set but might be null." >&2 else echo "It was was not set." >&2 fi
$@
에서 무언가를 확인하려는 경우 이를 수행하는 (훨씬) 더 나은 코드를 찾았습니다.
만약 [[ $1 = "" ]] 그 다음에 echo '$1은 비어있습니다' 또 다른 echo '$1 채워졌습니다' 파이
왜 이게 다야? $@
모든 것이 Bash에 존재하지만 기본적으로 비어 있으므로 test -z
및 test -n
이 도움이 되지 않습니다.
업데이트: 매개변수의 문자 수를 셀 수도 있습니다.
만약 [ ${#1} = 0 ] 그 다음에 echo '$1은 비어있습니다' 또 다른 echo '$1 채워졌습니다' 파이
if [[ ${!xx[@]} ]] ; then echo xx is defined; fi
나는 bash의 조잡한 세부 사항을 숨기는 보조 기능을 좋아합니다. 이 경우, 그렇게 하면 훨씬 더 (숨겨진) 조잡함이 추가됩니다.
# The first ! negates the result (can't use -n to achieve this) # the second ! expands the content of varname (can't do ${$varname}) function IsDeclared_Tricky { local varname="$1" ! [ -z ${!varname+x} ] }
이 구현에서 처음에 버그가 있었기 때문에(Jens와 Lionel의 답변에서 영감을 얻었습니다) 다른 솔루션을 생각해 냈습니다.
# Ask for the properties of the variable - fails if not declared function IsDeclared() { declare -p $1 &>/dev/null }
나는 그것이 더 간단하고 더 수줍고 이해/기억하기 쉽다는 것을 알았습니다. 테스트 케이스는 동등함을 보여줍니다:
function main() { declare -i xyz local foo local bar= local baz='' IsDeclared_Tricky xyz; echo "IsDeclared_Tricky xyz: $?" IsDeclared_Tricky foo; echo "IsDeclared_Tricky foo: $?" IsDeclared_Tricky bar; echo "IsDeclared_Tricky bar: $?" IsDeclared_Tricky baz; echo "IsDeclared_Tricky baz: $?" IsDeclared xyz; echo "IsDeclared xyz: $?" IsDeclared foo; echo "IsDeclared foo: $?" IsDeclared bar; echo "IsDeclared bar: $?" IsDeclared baz; echo "IsDeclared baz: $?" } main
하는 테스트 케이스도 보여줍니다 local var
( '='다음에하지 않는 한) VAR를 선언하지 않습니다. 꽤 오랫동안 나는 내가 단지 내 의도를 표현했다는 것을 발견하기 위해 이런 식으로 변수를 선언했다고 생각했습니다.
IsDeclared_Tricky xyz: 1
IsDeclared_Tricky foo: 1
IsDeclared_Tricky 막대: 0
IsDeclared_Tricky baz: 0
IsDeclared xyz: 1
IsDeclared foo: 1
IsDeclared 막대: 0
IsDeclared baz: 0
보너스: 사용 사례
저는 주로 이 테스트를 사용하여 다소 "우아하고" 안전한 방식으로(거의 인터페이스와 유사한...) 매개변수를 함수에 제공(및 반환)합니다.
#auxiliary functions function die() { echo "Error: $1"; exit 1 } function assertVariableDeclared() { IsDeclared "$1" || die "variable not declared: $1" } function expectVariables() { while (( $# > 0 )); do assertVariableDeclared $1; shift done } # actual example function exampleFunction() { expectVariables inputStr outputStr outputStr="$inputStr world!" } function bonus() { local inputStr='Hello' local outputStr= # remove this to trigger error exampleFunction echo $outputStr } bonus
모든 변수가 선언된 상태에서 호출되는 경우:
안녕하세요 세계입니다!
또 다른:
오류: 변수가 선언되지 않음: outputStr
출처 : http:www.stackoverflow.com/questions/3601515/how-to-check-if-a-variable-is-set-in-bash
원자 속성과 비 원자 속성의 차이점은 무엇입니까? (0) | 2021.12.26 |
---|---|
Git 커밋의 변경 사항을 어떻게 볼 수 있습니까? (0) | 2021.12.26 |
Android에서 화면 크기를 픽셀로 얻는 방법 (0) | 2021.12.26 |
문자열에 리터럴 중괄호 문자를 인쇄하고 .format을 사용하려면 어떻게 해야 합니까? (0) | 2021.12.26 |
재귀 적으로 어떻게 grep합니까? (0) | 2021.12.26 |