Bash에 변수가 설정되어 있는지 확인하는 방법은 무엇입니까?


1567

Bash에 변수가 설정되어 있는지 어떻게 알 수 있습니까?

예를 들어, 사용자가 함수에 첫 번째 매개 변수를 제공했는지 어떻게 확인합니까?

function a {
    # if $1 is set ?
}

12
if test $# -gt 0; then printf 'arg <%s>\n' "$@"; fi.
Jens

210
해결책을 찾는 사람을위한 참고 사항 :이 질문에 대한 답변은 "변수가 비어 있지 않습니다"라는 높은 등급의 답변이 많이 있습니다. Jens와 Lionel의 답변에 더 많은 수정 솔루션 ( "변수 세트")이 언급되어 있습니다.
Nathan Kidd

8
또한 Russell Harmon과 Seamus는 -v테스트 를 통해 정확 하지만 새로운 버전에서만 사용할 수 있지만 bash쉘을 통해 이식 할 수는 없습니다.
Graeme

5
@NathanKidd가 지적한 것처럼 Lionel과 Jens가 올바른 솔루션을 제공합니다. 눈에 띄게 받아 들여진 대답 을 다음 중 하나로 바꾸어야 합니다.
Garrett

3
... 또는 @prosseek가 문제를 해결하지 않기 때문에 우리 사이의 더 분별력에 의해 잘못된 대답이 다운 투표 될 수 있습니다.
dan3

답변:


2301

(보통) 올바른 방법

if [ -z ${var+x} ]; then echo "var is unset"; else echo "var is set to '$var'"; fi

어디 ${var+x}A는 매개 변수 확장 하면 아무것도로 평가 var해제하고, 문자열을 대체 x그렇지.

인용문

이 구문 및 사용법은 따옴표가 필요없는 항목으로 확장되거나 (단어 구분이 없으므로 따옴표가 필요하지 않으므로) 따옴표를 생략 할 수 있으므로 ( ${var+x}대신 대신 말할 수 "${var+x}"있음 x) 아무것도 (이 결과로 [ -z ]편리하게 동일한 값 (true)으로 편리하게 평가됨 [ -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" ]괜찮을 것입니다.


29
@Garrett, 귀하의 수정으로이 답변이 잘못 ${var+x}되었습니다. 를 사용 [ -z ${var:+x} ]하면와 다른 결과가 없습니다 [ -z "$var" ].
Graeme

11
작동하지 않습니다. var가 값으로 설정되어 있는지 여부에 관계없이 "설정되지 않음"이 표시됩니다 ( "unset var"로 지우면 "echo $ var"는 출력을 생성하지 않음).
Brent212

10
솔루션 구문 $ {parameter + word}의 공식 매뉴얼 섹션은 gnu.org/software/bash/manual/… ; 그러나 버그는이 구문을 명확하게 언급하지는 않지만 인용 (콜론 [ ":"] 생략)은 설정되지 않은 매개 변수에 대해서만 테스트를 수행한다는 것입니다. .. $ {parameter : + word} [means] 매개 변수가 널이거나 설정되지 않은 경우 대체되는 것이 없습니다. 그렇지 않으면 단어의 확장이 대체됩니다.); 인용 참조 pubs.opengroup.org/onlinepubs/9699919799/utilities/… (알아두면 좋은) 문서가 여기에 훨씬 더 명확합니다.
Destiny Architect

7
여러 표현식을 사용할 때 따옴표가 필요한 것처럼 보입니다 (예 : bash 4.3-ubuntu에서 [ -z "" -a -z ${var+x} ]가져 bash: [: argument expected옵니다 (예 : zsh는 아님). 어떤 경우에는 작동하는 구문을 사용하여 답변을 싫어합니다.
FauxFaux

41
간단한 것을 사용하는 [ -z $var ]것은 따옴표를 생략하는 것보다 더 이상 "잘못"되지 않습니다. 어느 쪽이든, 당신은 당신의 입력에 대해 가정합니다. 빈 문자열을 설정되지 않은 것으로 처리하는 [ -z $var ]것이 필요합니다.
nshew

909

null이 아닌 / 0이 아닌 문자열 변수를 확인하려면 (예 : 설정 한 경우)

if [ -n "$1" ]

의 반대입니다 -z. -n이상을 사용 하고 -z있습니다.

당신은 그것을 다음과 같이 사용할 것입니다 :

if [ -n "$1" ]; then
  echo "You supplied the first parameter!"
else
  echo "First parameter not supplied."
fi

86
나는 보통 선호 [[ ]]이상 [ ]으로, [[ ]]더 강력하고 특정 상황에서 적은 문제가 발생합니다 ( 이 질문에 둘 사이의 차이에 대한 설명을). 이 질문은 특히 bash 솔루션을 요구하며 이식성 요구 사항은 언급하지 않았습니다.
Flow

18
문제는 변수가 설정되어 있는지 어떻게 확인할 수 있는지 입니다 . 그런 다음 변수 설정 되었다고 가정 할 수 없습니다 .
HelloGoodbye

7
나는 []쉘 (비 bash) 스크립트에서 더 잘 작동 한다는 데 동의합니다 .
Hengjie


63
참고 -n기본 그래서 더 간단하게 테스트이며, [ "$1" ][[ $1 ]]뿐만 아니라 작동합니다. 또한 [[ ]] 인용 부호가 필요하지 않습니다 .
tne

478

다음은 매개 변수가 설정되지 않았는지 또는 비어 있는지 ( "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 : 파라미터 확장 :

"대체"로 표시된 모든 경우에 표현은 표시된 값으로 대체됩니다. "assign"으로 표시된 모든 경우에 매개 변수에 해당 값이 지정되며 표현식도 대체됩니다.

이것을 실제로 보여주기 위해 :

+--------------------+----------------------+-----------------+-----------------+
|   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           | ""              |
+--------------------+----------------------+-----------------+-----------------+

5
@HelloGoodbye 예 작동합니다 : set foo; echo ${1:-set but null or unset}echos "foo"; set --; echo ${1:-set but null or unset}echos set but null ...
Jens

4
@HelloGoodbye 위치 매개 변수는 다음과 같이 설정할 수 있습니다. set:-)
Jens

95
이 답변은 매우 혼란 스럽습니다. 이 테이블을 사용하는 방법에 대한 실제 예는 무엇입니까?
벤 데이비스

12
@ BenDavis 자세한 내용은 POSIX 표준에 대한 링크에 설명되어 있으며 표는이 장의 장을 참조합니다. 내가 쓰는 거의 모든 스크립트에서 사용하는 하나의 구문 : ${FOOBAR:=/etc/foobar.conf}은 변수가 설정되어 있지 않거나 null 인 경우 변수의 기본값을 설정하는 것입니다.
Jens

1
parameter변수 이름입니다. word는 사용중인 테이블의 구문과 변수 $parameter가 설정, 설정되어 있지만 null인지 또는 설정되지 않은지에 따라 대체 할 문자열 입니다. 일을 더 복잡하게 만들지 않고 word변수도 포함 할 수 있습니다! 이것은 문자로 구분 된 선택적 인수를 전달할 때 매우 유용 할 수 있습니다. 예를 들어 ${parameter:+,${parameter}}, ,$parameter설정되어 있지만 null이 아닌 경우 쉼표를 구분하여 출력합니다 . 이 경우, word,${parameter}
TrinitronX

260

여기에 언급 된 대부분의 기술은 정확하지만 bash 4.2 는 변수 값을 테스트하는 대신 변수 존재에 대한 실제 테스트 ( man bash )를 지원합니다.

[[ -v foo ]]; echo $?
# 1

foo=bar
[[ -v foo ]]; echo $?
# 0

foo=""
[[ -v foo ]]; echo $?
# 0

특히이 방법은을 사용하는 것과 같은 다른 많은 방법과 달리 set -u/ set -o nounset모드 에서 설정되지 않은 변수를 확인하는 데 사용될 때 오류가 발생하지 않습니다 [ -z.


9
bash 4.1.2에서 변수 설정 여부에 관계없이 [[ -v aaa ]]; echo $?==>-bash: conditional binary operator expected -bash: syntax error near 'aaa'
Dan

32
'test'내장에 대한 '-v'인수는 bash 4.2에 추가되었습니다.
Ti Strga

19
-v 인수는 -u 쉘 옵션 (ununset)의 보완으로 추가되었습니다. 'nounset'이 켜져 있으면 (set -u) 대화식이 아닌 경우 쉘은 오류를 리턴하고 종료됩니다. $ #은 위치 매개 변수를 확인하는 데 좋았습니다. 그러나 명명 된 변수는 변수를 설정되지 않은 것으로 식별하기 위해 클로버 링 이외의 다른 방법이 필요했습니다. 많은 사람들이 이전 버전과 호환되기 때문에이 기능이 너무 늦어서 유감스럽게도 사용할 수 없습니다. 다른 옵션은 위와 같이 트릭이나 '해킹'을 사용하여 주위를 돌아 다니는 것이지만 가장 우아합니다.
osirisgothra

2
선언되었지만 설정되지 않은 변수에는 작동하지 않습니다. 예declare -a foo
miken32

17
이것이 내가 받아 들일 수 있거나 가장 투표가 많은 답변을 계속 읽은 이유입니다.
Joe

176

다음 중 하나를 사용하여이를 수행하는 방법에는 여러 가지가 있습니다.

if [ -z "$1" ]

$ 1이 null이거나 설정되지 않은 경우 성공


46
설정되지 않은 매개 변수와 널값을 갖는 매개 변수 사이에는 차이가 있습니다.
chepner

21
난 그냥이가 체크 아웃 현학적 및 포인트가 될하려는 반대 무엇을 질문 포즈에 대한 답변. 변수가 설정되어 있지 않은지, 변수가 설정되어 있는지 묻습니다.
Philluminati 2016 년

47
[[ ]]이식성 함정에 지나지 않습니다. if [ -n "$1" ]여기에 사용되어야합니다.
Jens

73
이 답변은 잘못되었습니다. 이 질문은 변수가 비어 있지 않은 값으로 설정되어 있는지 여부가 아니라 변수가 설정되어 있는지 여부를 알려주는 방법을 묻습니다. 을 감안할 때 foo="", $foo값을 가지고 있지만, -z단지 비어 있다고보고합니다. 그리고 -z $foo당신이 있다면 날려 버릴 것 set -o nounset입니다.
Keith Thompson

4
"변수 설정"의 정의에 따라 다릅니다. 변수가 0이 아닌 문자열로 설정되어 있는지 확인하려면 mbranning answer 가 맞습니다. 당신이 변수가 선언되었지만 (즉, 초기화되어 있지 않은 경우 확인하고자한다면 foo=), 다음 러셀의 대답은 올바른 것입니다.
Flow

76

나는 항상 다른 답변 에서 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")그 결과는 변수의 원래의 값을 의미 하고 향후 사용을 위해 변수에 할당 제공된 대체 문자열.

1
실제 코딩 오류 인 변수 만 수정했습니다 (변수 작업시 원치 않는 간접 인스턴스). 달러가 설명을 해석하는 데 차이가있는 몇 가지 경우를 수정하기 위해 편집했습니다. BTW에서 모든 쉘 변수 (배열 제외)는 문자열 변수입니다. 숫자로 해석 될 수있는 문자열이 포함되어있을 수 있습니다. 줄에 대해 이야기하면 메시지가 흐려집니다. 따옴표는 문자열과 관련이 없으며 탈출의 대안 일뿐입니다. VARIABLE=""로 쓸 수 있습니다 VARIABLE=. 여전히 전자는 더 읽기 쉽습니다.
Palec

테이블에 감사드립니다. 매우 유용하지만 설정하지 않거나 비어 있으면 스크립트를 종료하려고합니다. 그러나 내가 얻는 종료 코드는 127이 아닌 1입니다.
우주 비행사

64

변수가 비어 있지 않은지 확인하기 위해

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

나도 이것을 오랫동안 사용했다; 감소 된 방식으로 :[ $isMac ] && param="--enable-shared"

@Bhaskar 이 답변 은 거의 반 년 전에 이미 본질적으로 동일한 대답 ( iff ${variable+x}를 얻는 데 사용됨)을 제공 했기 때문이라고 생각합니다 . 또한 왜 옳은지를 설명하는 훨씬 자세한 내용이 있습니다. x$variable
Mark Haferkamp

하지만, ${variable+x}(명백한) 덜 읽을 수
knocte

35

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

5
또한 [ -v "$VARNAME" ]정확하지는 않지만 단순히 다른 테스트를 수행합니다. 가정 VARNAME=foo; 그런 다음 이름 foo이 지정된 변수가 있는지 확인합니다 .
chepner

5
이식성을 원하는 사람들 -v은 POSIX를 준수하지 않습니다
kzh

하나를 얻는다면 [: -v: unexpected operator, bash대신에 사용해야 합니다 sh.
koppor

25
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

1
첫 번째 테스트는 거꾸로입니다. 나는 당신이 원하는 [ "$1" != "" ](또는 [ -n "$1" ]) 생각합니다 ...
Gordon Davisson

10
$1빈 문자열로 설정 하면 실패 합니다.
HelloGoodbye

2
답변의 두 번째 부분 (카운팅 매개 변수)은 $1빈 문자열로 설정되어 있을 때 답변의 첫 번째 부분이 작동하지 않는 경우 유용한 해결 방법입니다 .
Mark Berry

set -o nounset켜져 있으면 실패합니다 .
Flimm

21

노트

bash태그 때문에 Bash 중심의 답변을 많이 제공하고 있습니다.

짧은 답변

Bash에서 명명 된 변수 만 처리하는 한이 함수는 변수가 빈 배열 인 경우에도 변수가 설정되었는지 항상 알려줍니다.

variable-is-set() {
    declare -p "$1" &>/dev/null
}

왜 이것이 작동 하는가

Bash (최소한 3.0까지)에서 var선언 / 설정 변수 인 경우 현재 유형 및 값에 관계없이 변수 를 설정 declare -p var하는 declare명령 을 출력하고 var상태 코드 0(성공)를 반환합니다 . var선언되지 않은 경우 declare -p var오류 메시지를 출력하고 stderr상태 코드를 반환합니다 1. 을 사용 하면 상태 코드를 변경하지 않고 &>/dev/null일반 stdoutstderr출력을 모두로 리디렉션합니다 /dev/null. 따라서이 함수는 상태 코드 만 반환합니다.

Bash에서 다른 방법 (때로는)이 실패하는 이유

  • [ -n "$var" ]:${var[0]} 비어 있지 않은지 확인합니다 . (Bash $var에서와 동일합니다 ${var[0]}.)
  • [ -n "${var+x}" ]:${var[0]}설정되어 있는지 확인합니다 .
  • [ "${#var[@]}" != 0 ]: 적어도 하나의 인덱스 $var가 설정되어 있는지 확인합니다 .

이 방법이 Bash에서 실패한 경우

이것은 단지 (포함라는 이름의 변수를 작동 $_)이 아닌 특수한 변수 ( $!, $@, $#, $$, $*, $?, $-, $0, $1, $2, ...,하고 나는 잊어 버린 수 있습니다). 이들 중 어느 것도 배열이 아니기 때문에 POSIX 스타일 [ -n "${var+x}" ]은 이러한 모든 특수 변수에 대해 작동합니다. 그러나 많은 특수 변수는 함수가 호출 될 때 값 / 존재를 변경하므로 함수에 래핑하지 마십시오.

쉘 호환성 노트

스크립트에 배열이 있고 가능한 많은 쉘과 호환되도록하려는 경우 typeset -p대신 대신 사용을 고려하십시오 declare -p. ksh는 전자를 지원하지만 이것을 테스트 할 수는 없다는 것을 읽었습니다. 나는 배쉬 3.0 이상 및 zsh을 5.5.1 각 지원이 모두 것을 알고 typeset -pdeclare -p만 다른 것이있는 사람이 다른에 대한 대안입니다. 그러나 나는 그 두 키워드 이상의 차이점을 테스트하지 않았으며 다른 쉘을 테스트하지 않았습니다.

POSIX sh 호환 스크립트가 필요하면 배열을 사용할 수 없습니다. 배열이 없으면 [ -n "{$var+x}" ]작동합니다.

Bash의 다른 메소드에 대한 비교 코드

이 기능 설정 해제 변수 var, eval상기 S는 코드 전달 여부를 결정하는 테스트를 실행 var에 의해 설정되는 evalD 코드 최종적 다른 시험 결과의 상태 코드를 보여준다.

나는 건너 뛰는거야 test -v var, [ -v var ]그리고 [[ -v var ]]그들이 POSIX 표준을 동일한 결과를 얻을 수 있기 때문에 [ -n "${var+x}" ], 배쉬 4.2 이상을 요구하면서. 테스트 한 쉘 (Bash 3.0 ~ 5.0 및 Zsh 5.5.1)과 typeset -p동일하기 때문에 건너 뜁니다 declare -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
}

테스트 케이스 코드

변수가 연관 배열로 선언되지 않은 경우 숫자가 아닌 배열 인덱스를 "0"으로 처리하는 Bash로 인해 테스트 결과가 예기치 않게 나타날 수 있습니다. 또한 연관 배열은 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 3.0 이후 Bash에서 명명 된 변수를 테스트 할 때 (100 %?) 신뢰할 수 있습니다.
  • [ -n "${var+x}" ] POSIX 호환 상황에서는 안정적이지만 어레이를 처리 할 수 ​​없습니다.
  • 변수가 비어 있지 않은지 확인하고 다른 쉘에서 선언 된 변수를 확인하기위한 다른 테스트가 있습니다. 그러나 이러한 테스트는 Bash 나 POSIX 스크립트에는 적합하지 않습니다.

3
내가 시도한 답변 declare -p var &>/dev/null중이 하나만 작동합니다. 감사합니다!
user1387866

2
@ mark-haferkamp 함수 코드에 중요한 선행 "/"를 추가하기 위해 답을 편집하려고했지만 읽을 수 ... &> /dev/null는 없으므로 단일 문자 편집을 할 수는 없습니다. 그러나 그것은 작동하지 않았습니다). 또한 지적한 것처럼 $1이름이 지정된 변수 (예 :)에 대해 전환하도록 함수를 변경하는 것이 OUTPUT_DIR좋습니다 $1. 어쨌든, 그것은 중요한 편집입니다. 그렇지 않으면 코드는이라는 null상대 디렉토리에있는 파일을 작성하려고합니다 dev. BTW-좋은 답변입니다!
joehanna

또한 $ 접두어없이 변수의 이름을 사용하면 작동합니다. declare -p PATH &> /dev/nullreturns 0 where as declare -p ASDFASDGFASKDF &> /dev/nullreturns 1 (bash. 5.0.11 (1) -release)
joehanna

1
훌륭한 일! 주의 사항 1 개 : declare varvar 변수를 선언하지만 다음 과 같이 설정 하지는 않습니다set -o nounset .declare foo bar=; set -o nounset; echo $bar; echo $foo
xebeche로

@joehanna 누락 된 것을 발견해 주셔서 감사합니다 /! 나는 그것을 고쳤 지 만 논리는 특히 @xebeche의 의견에 비추어 함수를 보증하기에 충분히 혼란 스럽다고 생각합니다. @xebeche 저의 대답에는 불편합니다.… declare -p "$1" | grep =또는 같은 것을 시도해야 할 것 같습니다 test -v "$1".
Mark Haferkamp

19

다음 을 사용하여 스크립트에서 설정되지 않았거나 비어 있는지 확인하려는 사용자의 경우 set -u:

if [ -z "${var-}" ]; then
   echo "Must provide var environment variable. Exiting...."
   exit 1
fi

정규 [ -z "$var" ]검사는 var; unbound variableif로 실패 set -u하지만 실패하지 않고 설정되지 않으면 빈 문자열로 [ -z "${var-}" ] 확장 됩니다 var.


콜론이 없습니다. 그것은해야 ${var:-}하지 ${var-}. 그러나 Bash에서는 콜론 없이도 작동하는지 확인할 수 있습니다.
Palec

3
${var:-}그리고 ${var-}다른 것을 의미한다. ${var:-}경우 문자열을 비우 확장됩니다 var해제 또는 null${var-}만 설정되지 않은 경우 빈 문자열로 확장됩니다.
RubenLaguna

새로운 것을 배웠습니다, 감사합니다! 콜론을 생략하면 설정되지 않은 매개 변수에 대해서만 테스트가 수행됩니다. 다시 말해, 콜론이 포함되면 연산자는 매개 변수의 존재 여부와 그 값이 널이 아닌지 테스트합니다. 콜론이 생략되면 연산자는 존재 여부 만 테스트합니다. 여기에는 차이가 없지만 알아두면 좋습니다.
Palec

17

설정이 해제되면 종료하고 싶습니다

이것은 나를 위해 일했습니다. 매개 변수가 설정되지 않은 경우 스크립트가 오류 메시지와 함께 종료되기를 원했습니다.

#!/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


15

변수가 비어 있지 않은 값으로 설정되어 있는지 확인하려면 [ -n "$x" ]다른 지시자가 이미 표시 한대로를 사용하십시오 .

대부분 빈 값을 가진 변수를 설정되지 않은 변수와 같은 방식으로 처리하는 것이 좋습니다. 그러나 필요한 경우 두 가지를 구별 할 수 있습니다. [ -n "${x+set}" ]( if 가 설정 "${x+set}"되어 set있으면 x빈 문자열로 확장됩니다.x 설정되지 않은 )

매개 변수가 전달되었는지 확인하려면 test $#또는 함수에 전달 된 매개 변수의 수인 test 또는 함수에없는 스크립트에 전달하십시오 ( Paul 's answer 참조 ).


14

의 "매개 변수 확장"섹션을 읽으십시오 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이 예에서는 아무 것도 수행하고 싶지 않습니다. 설정되지 않은 경우 종료하면됩니다)


1
나는 다른 답변들 중 누구도 간단하고 우아하다고 언급하지 않았다 : ${var?message}.
tripleee

어디서 이걸 가져 갔니? 훌륭한! 그냥 작동합니다! 그리고 짧고 우아합니다! 감사합니다!
Roger

13

bash에서는 내장 -v내부에서 사용할 수 있습니다 [[ ]].

#! /bin/bash -u

if [[ ! -v SOMEVAR ]]; then
    SOMEVAR='hello'
fi

echo $SOMEVAR

8

[[ -z "$var" ]]변수 사용 여부를 알 수있는 가장 쉬운 방법은 사용 이지만,이 옵션 -z은 설정되지 않은 변수와 빈 문자열로 설정된 변수를 구별하지 않습니다.

$ set=''
$ [[ -z "$set" ]] && echo "Set" || echo "Unset" 
Unset
$ [[ -z "$unset" ]] && echo "Set" || echo "Unset"
Unset

변수 유형 (env variable, parameter 또는 regular variable)에 따라 확인하는 것이 가장 좋습니다.

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 리턴 코드에 영향을주지 않고 출력을 억제 합니다.

5

Bash 옵션 set -u이 활성화되어 있으면 위의 답변이 작동하지 않습니다 . 또한 동적이지 않습니다. 예를 들어 "dummy"라는 이름으로 변수를 테스트하는 방법이 정의되어 있습니까? 이 시도:

is_var_defined()
{
    if [ $# -ne 1 ]
    then
        echo "Expected exactly one argument: variable name as string, e.g., '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.
}

관련 : Bash에서 변수가 "-u"모드로 정의되어 있는지 테스트하는 방법


1
이 답변이 다운 보트 된 이유를 너무 많이 알고 싶습니다.
LavaScornedOven

Bash에서는 eval 없이도 동일한 작업을 수행 할 수 있습니다 . eval "[ ! -z \${$1:-} ]"간접 평가로 변경 : [ ! -z ${!1:-} ];.

@BinaryZebra : 재미있는 아이디어. 별도의 답변으로 게시하는 것이 좋습니다.
kevinarpe

"eval"을 사용하면이 솔루션이 코드 삽입에 취약 해집니다 : $ is_var_defined 'x}]; 에코 "gotcha"> & 2; # '
gotcha


4

내가 선호하는 방법은 다음과 같습니다.

$ 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이됩니다 (따라서 false"설정되지 않음"으로 종료됩니다 ).



1

셸에서는 -z문자열 길이가 0 인 경우 True 인 연산자를 사용할 수 있습니다 .

설정 MY_VAR되지 않은 경우 기본값을 설정하는 간단한 단일 라이너 , 그렇지 않으면 선택적으로 메시지를 표시 할 수 있습니다.

[[ -z "$MY_VAR" ]] && MY_VAR="default"
[[ -z "$MY_VAR" ]] && MY_VAR="default" || echo "Variable already set."

0
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, $2최대는 $N항상 설정됩니다. 죄송합니다. 실패입니다.

나는 그것을 시도했지만 작동하지 않았다. 아마도 내 배쉬 버전은 그것에 대한 지원이 부족하다. Idk, 내가 틀렸다면 죄송합니다. :)

0

에서 무언가를 확인하려면이 작업을 수행하는 훨씬 더 나은 코드를 찾았습니다 $@.

[[$ 1 = ""]] 인 경우
그때
  에코 '$ 1이 비어 있습니다'
그밖에
  에코 '$ 1이 채워졌습니다'
fi

왜이 모든거야? 모든에 $@배쉬에 존재하지만, 기본적으로의 빈, 그래서 test -z하고 test -n당신을 도울 수 있습니다.

업데이트 : 매개 변수에서 문자 수를 계산할 수도 있습니다.

[$ {# 1} = 0] 인 경우
그때
  에코 '$ 1이 비어 있습니다'
그밖에
  에코 '$ 1이 채워졌습니다'
fi

알아,하지만 그게 다야 비어있는 것이 있으면 오류가 발생합니다! 죄송합니다. : P

0
if [[ ${!xx[@]} ]] ; then echo xx is defined; fi

11
StackOverflow에 오신 것을 환영합니다. 귀하의 답변은 높이 평가되지만 코드 이상의 것을 제공하는 것이 가장 좋습니다. 답이나 작은 설명에 추론을 추가 할 수 있습니까? 답변 확장에 대한 다른 아이디어는 이 페이지 를 참조하십시오 .
Celeo

0

이것이 내가 매일 사용하는 것입니다.

#
# Check if a variable is set
#   param1  name of the variable
#
function is_set()
{
    [[ -n "${1}" ]] && test -n "$(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$ mavar=""
bash-3.00$ is_set myvar ; echo $?
0
bash-3.00$ unset myvar
bash-3.00$ is_set myvar ; echo $?
1

1
Bash 2.0 이상에서 간접 확장이 가능합니다. test -n "$(eval "echo "\${${1}+x}"")"동등 물에 대해 길고 복잡한 (eval도 포함하여) 대체 할 수 있습니다 .[[ ${!1+x} ]]

0

나는 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

테스트 사례는 또한 var를 선언 local 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


0

모든 답변을 감추고 나면 다음과 같이 작동합니다.

if [[ -z $SOME_VAR ]]; then read -p "Enter a value for SOME_VAR: " SOME_VAR; fi
echo "SOME_VAR=$SOME_VAR"

SOME_VAR내가 가진 것 대신에 넣지 않으면 $SOME_VAR빈 값으로 설정됩니다. $이것이 작동하려면 필요합니다.


당신이있을 때 작동하지 않습니다 set -u인쇄되는 효과 unboud variable오류
마이클 Heuberger

-1

var가 설정되어 있는지 확인하려면

var=""; [[ $var ]] && echo "set" || echo "not set"

3
$var빈 문자열로 설정 하면 실패 합니다.
HelloGoodbye

-1

변수가 바운드 또는 언 바운드인지 테스트하려면 nounset 옵션을 설정 한 후에도 잘 작동합니다.

set -o noun set

if printenv variableName >/dev/null; then
    # variable is bound to a value
else
    # variable is unbound
fi

당신이 set -o nounset아니라고 생각합니다 set -o noun set. 이것은 exported 된 변수에 대해서만 작동합니다 . 또한 실행 취소하기 어려운 방식으로 설정을 변경합니다.
Keith Thompson

-1

나는 항상 처음으로 코드를 보는 사람이 이해하기 쉽다는 사실에 근거하여 항상 이것을 사용합니다.

if [ "$variable" = "" ]
    then
    echo "Variable X is empty"
fi

그리고 비어 있지 않은지 확인하려면;

if [ ! "$variable" = "" ]
    then
    echo "Variable X is not empty"
fi

그게 다야.


4
질문은 변수가 비어 있는지가 아니라 변수가 설정되어 있는지 확인하는 방법을 묻습니다.
HelloGoodbye

[[ ... ]]대신 을 사용해야 합니다 [ ... ]. 후자는 실제로 외부 명령이며 변수 설정 여부에 대한 가시성이 없습니다.
solidsnack
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.