변수가 'if'문에 있는지 어떻게 확인합니까?


69

if명령문 에 변수가 있는지 확인해야 합니다. 다음과 같은 효과가 있습니다.

if [ -v $somevar ]
then
    echo "Variable somevar exists!"
else
    echo "Variable somevar does not exist!"

그리고 가장 가까운 질문은 this 이며 실제로 내 질문에 대답하지 않습니다.


$somevar변수가없는 경우 값 / 문자열 로 설정하려는 경우 : ${somevar:=42}.
Cyrus

개인적으로 나는 공허함 ( [ -n "$var" ]또는 [ ! -z "$var" ]) 만 확인하는 경향이 있습니다. 존재 / 존재 확인이 너무 미묘하다고 생각하며 코드가 거칠고 단순합니다.
PSkocik

답변:


97

최신 배쉬 (버전 4.2 이상)에서 :

[[ -v name_of_var ]]

보낸 사람 help test:

-v VAR, 쉘 변수 VAR이 설정된 경우 True


3
단일 괄호와 함께 작동합니다 : [ -v name_of_var ].
meuh

7
해시 및 배열의 ​​경우 변수에 키 / 인식 "0"요소가 없으면 false를 반환합니다. nameref의 경우 대상이 정의되어 있는지 테스트합니다. 이 같은 특별한 매개 변수 작동하지 않습니다 $1, $-, $#...
스테판 Chazelas가

4
이 기능은 bash 내장 test또는 [; 에서 사용할 수 없습니다 /usr/bin/test. man test와 비교하십시오 help test.
Mark Lakata

외부 명령이 쉘의 내부 상태를 알 수 없기 때문에 @MarkLakata 맞습니다.
Chris Down

음 항상 항상 [[-v "$ name_of_var"]]해서는 안됩니까?
Alexander Mills

24

당신이 의미하는 바에 달려 있습니다 .

선언되었지만 할당되지 않은 변수 있습니까?

빈 목록이 할당 된 배열 (또는 해시) 변수 있습니까?

현재 할당되지 않은 변수를 가리키는 nameref 변수 있습니까?

당신은 생각하십니까 $-, $#, $1변수? (POSIX는 그렇지 않습니다).

Bourne과 같은 껍질에서 표준 방법은 다음과 같습니다.

if [ -n "${var+set}" ]; then
  echo '$var was set'
fi

즉 (assigments, 자동, 빈 여부, 환경에서 변수에 값이 할당되어있는 경우 알려 스칼라 변수 및 기타 매개 변수를 작동 read, for또는 다른).

typeset또는 declare명령 이있는 쉘의 경우 ,를 제외하고 선언 되었지만 할당 되지 않은 변수를 세트로 보고 하지 않습니다 .zsh

를 제외하고, 배열을 지원하는 쉘의 경우 yashzsh그대로보고하지 않을 설정 indice 0의 요소가 설정되어 있지 않은 경우 배열 변수.

들어 bash(그러나 ksh93zsh), 유형의 변수를 연관 배열 , 그 그들을보고하지 것이다 세트 키 "0"으로 설정되어 자신의 요소를 제외하고.

들어 ksh93bash, 형의 변수 nameref , 만 true를 돌려 nameref에 의해 참조 변수 자체는 고려 경우 세트 .

의 경우 ksh, zshbash, 잠재적으로 더 나은 방법이 될 수있다 :

if ((${#var[@]})); then
  echo '$var (or the variable it references for namerefs) or any of its elements for array/hashes has been set'
fi

를 들어 ksh93, zshbash4.4 이상,도있다 :

if typeset -p var 2> /dev/null | grep -q '^'; then
  echo '$var exists'
fi

설정되거나 선언 된 변수를보고합니다.


1
declare -p/ 지금도 typeset -p작동합니다 bash.
cas

1
@cas, 아니 선언되지 않았지만 변수를 설정하지 않았습니다. 시도 bash -c 'typeset -i a; typeset -p a'와 비교 ksh93zsh.
Stéphane Chazelas

+1 감사합니다. 또한 내 질문을 참조하십시오 unix.stackexchange.com/q/280893/674
Tim

bash-4.4로 변경된 @cas (2016 년 9 월에 릴리스 됨)를 편집했습니다.
Stéphane Chazelas

9

SO 에 대한 답변에서 언급했듯이 다음을 확인하는 방법이 있습니다.

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

여기서 $ {somevar + x}는 var가 설정되지 않은 경우 null로 평가되고 그렇지 않으면 문자열 "x"를 대체하는 매개 변수 확장입니다.

-n다른 답변에서 제안한대로를 사용 하면 변수에 빈 문자열이 포함되어 있는지 확인합니다. 존재 여부를 확인하지 않습니다.


2
$somevar처리 하려면 인용해야합니다 IFS=x. 또는 인용문 x.
mikeserv 2016 년

1
@ mikeserv 고마워, 나는 에지 사례에 대해 배우는 것을 좋아합니다 :) 당신은 의미 if [ -z "${somevar+x}" ]합니까? 여전히 내부에 필요한 인용이겠습니까 [[]]?
Tom Hale

@TomHale-예, 드문 경우입니다. [ test시험의 호출로 렌더링하기 위해 의존해야하는 일반적인 방법으로 주문 당신이 어떤 프로그램 명령 라인으로하여 읽을되도록해야하는 것을 적용되는 루틴은 명령 줄 매개 변수, 그래서 보통의 확장 및 해석에 동의합니다. test {! + "!"}
mikeserv

@ mikeserv 나는 당신의 예가 내 두 번째 질문에 있다고 생각합니다 ... 첫 번째도 예입니까?
Tom Hale

1
+1; 이것은 set -u효력이 있고 Bash 버전이 4.2 이전 인 경우 가장 간단한 방법으로 보입니다 .
Kyle Strand

4

POSIXly :

! (: "${somevar?}") 2>/dev/null && echo somevar unset

또는 쉘이 메시지를 표시하도록 할 수 있습니다.

(: "${somevar?}")
zsh: somevar: parameter not set

@ mikeserv : 예, 물론 할 수있는 많은 방법이 있습니다. 먼저, 나는 이것을 이것을 복제 할 것이라고 생각 합니다 . 그러나이 질문에서 OP는 확인 만하고 싶어합니다. 변수가 설정되지 않은 경우 종료하거나보고한다고 주장하지 않았으므로 서브 쉘에서 확인했습니다.
cuonglm 2016 년

2
글쎄, 알고 있지만 정확히 여기에서 테스트하는 가장 좋은 방법이 아닐 수 있음을 나타내는 것과 같은 하위 셸에서 수행해야하기 때문에 실패에 대한 중단 조치이므로 간단한 수단으로는 처리 할 수 ​​없습니다. 실패. 이식 심지어는 trap단지 EXIT에서 작업 할 수 있습니다. 그것이 내가 말하는 전부입니다. 합격 / 실패로는 적용되지 않습니다. 그리고 이것은 나도 말하는 것이 아닙니다. 나는 전에 이것을 정확하게 했으므로 저를 설득하기 위해 이와 같이 약간의 주석 채팅이 필요했습니다. 그래서 나는 그것을 앞으로 지불 할 것이라고 생각했습니다.
mikeserv 2016 년

1
@ mikeserv : 글쎄, 그것은 좋은 지적입니다. OP가 다음 구문과 혼동 될 수 있다는 점만 궁금합니다 :)
cuonglm

2
if set|grep '^somevar=' >/dev/null;then
    echo "somevar exists"
else
    echo "does not exist"
fi

나는 이것이 다소 비효율적이라고 생각할 것이지만, 그것은 매우 간단하고 sh호환 가능하며, 그것은 내가 필요한 것입니다.
hoijui

2
printf ${var+'$var exists!\n'}

... 그렇지 않으면 아무 것도 인쇄하지 않습니다. 또는...

printf $"var does%${var+.}s exist%c\n" \ not !

어느 쪽이든 말해 줄 것이다.

테스트의 반환 값을 사용하여 조건에 적합한 형식 문자열로 동적으로 확장 할 수 있습니다.

[ "${var+1}" ]
printf $"var does%.$?0s exist%c\n" \ not !

printf대체를 기반으로 실패 할 수도 있습니다 ...

printf $"var does%${var+.}s exist%c\n%.${var+b}d" \
        \ not ! \\c >&"$((2${var+-1}))" 2>/dev/null

... 설정되지 않은 $var does not exist!경우 stderr 로 인쇄 하고 0 이외의 값을 반환 $var하지만 설정되면 $var does exist!stdout으로 인쇄 하고 0을 반환합니다 $var.


1

이 간단한 라인은 작동하며 대부분의 POSIX 쉘에서 작동합니다.

${var+"false"} && echo "var is unset"

또는 더 긴 형식으로 작성하십시오.

unset var

if ${var+"false"}
then
   echo "var is unset"
fi

확장은 다음과 같습니다

  • var에 값이 있으면 (널조차도) false가 바뀝니다.
  • var에 "값 없음"이 있으면 "값 없음"(널)이 바뀝니다.

${var+"false"}확장은 "거짓"중 "널 (null)"로 확장됩니다.
그런 다음 "nothing"또는 "false"가 실행되고 종료 코드가 설정됩니다.

종료 값은 확장 자체 (실행)에 의해 설정 되므로 명령 test( [또는 [[) 을 호출 할 필요가 없습니다 .


예, $IFSf, a, l, s 또는 e를 포함 할 때 sh 에뮬레이션의 일부 이전 버전의 zsh를 제외하고 . 다른 답변과 마찬가지로 배열, 해시 또는 언급 할 수있는 다른 유형의 변수가 있습니다.
Stéphane Chazelas

@ StéphaneChazelas 내가 썼습니다 most POSIX shells. 모두를 most 의미하는In the greatest number of instances 것은 아닙니다. ... ... 그래서, 모호한 조건 when $IFS contains f, a, l, s or e과 일부 모호한 껍질에 대해서는 some old versions of zsh이것이 실패합니다 : 얼마나 충격적입니까!. 그러한 버그가 오래 전에 해결되었다고 가정해야합니다. ... ... 오래 전에 깨진 쉘을 위해 코드를 작성해야한다고 제안하고 있습니까?

@ StéphaneChazelas 또한 : 질문 제목은 매우 구체적입니다 : Bash.

이진 얼룩말 ???
mikeserv

0

순수한 껍질 방법 :

[ "${var+1}" ] || echo "The variable has not been set"

테스트 스크립트 :

#!/bin/sh
echo "Test 1, var has not yet been created"
[ "${var+1}" ] || echo "The variable has not been set"

echo "Test 2, var=1"
var=1
[ "${var+1}" ] || echo "The variable has not been set"

echo "Test 3, var="
var=
[ "${var+1}" ] || echo "The variable has not been set"

echo "Test 4, unset var"
unset var
[ "${var+1}" ] || echo "The variable has not been set"
echo "Done"

결과 :

Test 1, var has not yet been created
The variable has not been set
Test 2, var=1
Test 3, var=
Test 4, unset var
The variable has not been set
Done

1
변수가 null 문자열로 설정되면 실패합니다.
Tom Hale

0

bash 4.4.19에서는 다음이 나를 위해 일했습니다. 여기 완전한 예가 있습니다

$export MAGENTO_DB_HOST="anyvalue"

#!/bin/bash

if [ -z "$MAGENTO_DB_HOST" ]; then
    echo "Magento variable not set"
else
    echo $MAGENTO_DB_HOST
fi

-1

ifbash에서 선언 된 변수의 존재를 확인하기 위해 명령을 사용할 수는 없지만 -v새로운 bash에는 옵션이 있지만 이식성이 없으므로 이전 bash버전에서는 사용할 수 없습니다 . 변수가 존재하지 않으면 변수를 사용할 때 동시에 생성되기 때문입니다.

예를 들어 MYTEST변수 를 사용하지 않거나 변수에 값을 할당했다고 가정 하지만 echo 명령을 사용하면 아무것도 표시하지 않습니다! 또는 사용 if [ -z $MYTEST ]하는 경우 0 값을 반환했습니다! 이 변수가 존재하지 않음을 알려주는 다른 종료 상태를 리턴하지 않았습니다!

이제 두 가지 솔루션이 있습니다 ( -v옵션 없음 ).

  1. declare명령을 사용 합니다.
  2. set명령을 사용 합니다.

예를 들면 다음과 같습니다.

MYTEST=2
set | grep MYTEST
declare | grep MYTEST

그러나 불행히도이 명령은 메모리에 함수를로드했음을 보여줍니다! declare -p | grep -q MYTEST ; echo $?더 깨끗한 결과를 위해 명령을 사용할 수 있습니다 .


-1

변수가 선언 / 설정 해제되었는지 확인하는 기능

빈 포함 $array=()


@Gilles의 답변 외에도

case " ${!foobar*} " in
  *" foobar "*) echo "foobar is declared";;
  *) echo "foobar is not declared";;
esac

-함수 내에서 캡슐화하는 방법을 찾지 못했습니다-부분적으로 Richard Hansen답변을 기반으로 하지만 간단한 버전을 추가하고 싶습니다. array=():

# The first parameter needs to be the name of the variable to be checked.
# (See example below)

var_is_declared() {
    { [[ -n ${!1+anything} ]] || declare -p $1 &>/dev/null;}
}

var_is_unset() {
    { [[ -z ${!1+anything} ]] && ! declare -p $1 &>/dev/null;} 
}
  • 변수가 (un) 설정되어 있는지 먼저 테스트하면 필요하지 않은 경우 선언 호출을 피할 수 있습니다.
  • 그러나 $1empty의 이름이 포함되어 있으면 $array=()선언 호출로 올바른 결과를 얻을 수 있습니다.
  • 변수가 설정되지 않았거나 빈 배열 인 경우에만 선언이 호출되므로 / dev / null에 전달 된 데이터는 많지 않습니다.


다음 코드를 사용하여 기능을 테스트 할 수 있습니다.

( # start a subshell to encapsulate functions/vars for easy copy-paste into the terminal
  # do not use this extra parenthesis () in a script!

var_is_declared() {
    { [[ -n ${!1+anything} ]] || declare -p $1 &>/dev/null;}
}

var_is_unset() {
    { [[ -z ${!1+anything} ]] && ! declare -p $1 &>/dev/null;} 
}

:;       echo -n 'a;       '; var_is_declared a && echo "# is declared" || echo "# is not declared"
a=;      echo -n 'a=;      '; var_is_declared a && echo "# is declared" || echo "# is not declared"
a="sd";  echo -n 'a="sd";  '; var_is_declared a && echo "# is declared" || echo "# is not declared"
a=();    echo -n 'a=();    '; var_is_declared a && echo "# is declared" || echo "# is not declared"
a=("");  echo -n 'a=("");  '; var_is_declared a && echo "# is declared" || echo "# is not declared"
unset a; echo -n 'unset a; '; var_is_declared a && echo "# is declared" || echo "# is not declared"
echo ;
:;       echo -n 'a;       '; var_is_unset a && echo "# is unset" || echo "# is not unset"
a=;      echo -n 'a=;      '; var_is_unset a && echo "# is unset" || echo "# is not unset"
a="foo"; echo -n 'a="foo"; '; var_is_unset a && echo "# is unset" || echo "# is not unset"
a=();    echo -n 'a=();    '; var_is_unset a && echo "# is unset" || echo "# is not unset"
a=("");  echo -n 'a=("");  '; var_is_unset a && echo "# is unset" || echo "# is not unset"
unset a; echo -n 'unset a; '; var_is_unset a && echo "# is unset" || echo "# is not unset"
)

스크립트는

a;       # is not declared
a=;      # is declared
a="foo"; # is declared
a=();    # is declared
a=("");  # is declared
unset a; # is not declared

a;       # is unset
a=;      # is not unset
a="foo"; # is not unset
a=();    # is not unset
a=("");  # is not unset
unset a; # is unset

-1

스칼라배열 유형 모두에 대해 작동하는 bash 함수 :

정의

has_declare() { # check if variable is set at all
    local "$@" # inject 'name' argument in local scope
    &>/dev/null declare -p "$name" # return 0 when var is present
}

기도

if has_declare name="vars_name" ; then
   echo "variable present: vars_name=$vars_name"
fi
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.