[bash] 쉘 스크립트에서 부울 변수를 어떻게 선언하고 사용할 수 있습니까?

다음 구문을 사용하여 쉘 스크립트에서 부울 변수를 선언하려고했습니다.

variable=$false

variable=$true

이 올바른지? 또한 해당 변수를 업데이트하려면 동일한 구문을 사용합니까? 마지막으로 부울 변수를 표현식으로 사용하기위한 다음 구문이 올바른가요?

if [ $variable ]

if [ !$variable ]



답변

수정 된 답변 (2014 년 2 월 12 일)

the_world_is_flat=true
# ...do something interesting...
if [ "$the_world_is_flat" = true ] ; then
    echo 'Be careful not to fall off!'
fi

원래 답변

경고 : https://stackoverflow.com/a/21210966/89391

the_world_is_flat=true
# ...do something interesting...
if $the_world_is_flat ; then
    echo 'Be careful not to fall off!'
fi

보낸 사람 : Bash에서 부울 변수 사용

원래 답변이 여기에 포함 된 이유는 2014 년 2 월 12 일 수정 이전의 주석은 원래 답변에만 관련되어 있으며 수정 된 답변과 관련하여 많은 주석이 잘못 되었기 때문입니다. 예를 들어, true2010 년 6 월 2 일에 내장 된 bash 에 대한 Dennis Williamson의 의견은 수정되지 않은 원래 답변에만 적용됩니다.


답변

TL; DR

bool=true

if [ "$bool" = true ]

Miku의 ( 원본 ) 답변 관련 문제

허용 된 답변 1을 권장 하지 않습니다 . 그것의 문법은 꽤 있지만 약간의 결함이 있습니다.

다음과 같은 조건이 있다고 가정하십시오.

if $var; then
  echo 'Muahahaha!'
fi

다음 경우 2 에서는이 조건이 true로 평가되고 중첩 된 명령이 실행됩니다.

# Variable var not defined beforehand. Case 1
var=''  # Equivalent to var="".        Case 2
var=    #                              Case 3
unset var  #                           Case 4
var='<some valid command>'  #          Case 5

일반적 var으로이 예에서 “부울”변수 가 명시 적으로 true로 설정된 경우에만 조건을 true로 평가 하려고합니다. 다른 모든 경우는 위험하게 오도됩니다!

마지막 경우 (# 5)는 변수에 포함 된 명령을 실행하기 때문에 특히 좋지 않습니다 (유효한 명령 3, 4에 대해 조건이 true로 평가되는 이유 ).

다음은 무해한 예입니다.

var='echo this text will be displayed when the condition is evaluated'
if $var; then
  echo 'Muahahaha!'
fi

# Outputs:
# this text will be displayed when the condition is evaluated
# Muahahaha!

변수를 인용하는 것이 더 안전합니다 (예 🙂 if "$var"; then. 위의 경우 명령을 찾을 수 없다는 경고가 표시됩니다. 그러나 우리는 여전히 더 잘할 수 있습니다 (하단의 권장 사항 참조).

또한 Miku의 원래 답변에 대한 Mike Holt의 설명을 참조하십시오.

Hbar의 답변 관련 문제

이 방법은 또한 예상치 못한 행동을합니다.

var=false
if [ $var ]; then
  echo "This won't print, var is false!"
fi

# Outputs:
# This won't print, var is false!

위의 조건이 false로 평가되므로 중첩 명령문을 실행하지 마십시오. 놀라다!

값 ( "false")을 인용하거나 변수 ( "$var")를 인용 test하거나 또는 [[대신 또는를 사용하여 [차이를 만들지 마십시오.

어떻게 않는 것이 좋습니다

“부울”을 확인하는 것이 좋습니다. 그들은 예상대로 작동합니다.

bool=true

if [ "$bool" = true ]; then
if [ "$bool" = "true" ]; then

if [[ "$bool" = true ]]; then
if [[ "$bool" = "true" ]]; then
if [[ "$bool" == true ]]; then
if [[ "$bool" == "true" ]]; then

if test "$bool" = true; then
if test "$bool" = "true"; then

그것들은 모두 거의 같습니다. 다른 답변 5 의 접근법보다 키 입력을 몇 번 더 입력 해야하지만 코드가 더 방어 적입니다.


각주

  1. Miku의 답변은 이후 편집되었으며 더 이상 (알려진) 결함이 없습니다.
  2. 철저한 목록이 아닙니다.
  3. 이 문맥에서 유효한 명령은 존재하는 명령을 의미합니다. 명령이 올바르게 사용되거나 잘못 사용되는지는 중요하지 않습니다. man woman그러한 매뉴얼 페이지가 존재하지 않더라도 예를 들어 유효한 명령으로 간주됩니다.
  4. 존재하지 않는 유효하지 않은 명령의 경우 Bash는 해당 명령을 찾을 수 없다고 간단히 불평합니다.
  5. 길이에 관심이 있다면 첫 번째 권장 사항이 가장 짧습니다.

답변

여기서 Bash builtin true과 좀 더 구체적으로 말하면 Bash가 대괄호 안의 표현식을 확장하고 해석하는 방법 에 대한 오해가있는 것 같습니다 .

miku의 답변 에있는 코드 는 Bash builtin true, 또는 /bin/true다른 맛의 true명령 과 전혀 관련이 없습니다 . 이 경우 true단순한 문자열에 지나지 true않으며, 변수 할당이나 조건식의 평가로도 ​​명령 / 내장을 호출하지 않습니다 .

다음 코드는 기능적으로 miku의 답변 코드와 동일합니다.

the_world_is_flat=yeah
if [ "$the_world_is_flat" = yeah ]; then
    echo 'Be careful not to fall off!'
fi

여기서 유일한 차이점은 비교되는 4 개의 문자가 ‘t’, ‘r’, ‘u’및 ‘e’대신 ‘y’, ‘e’, ​​’a’및 ‘h’라는 것입니다. 그게 다야. yeahBash가 token을 구문 분석 할 때 이름이 지정된 명령이나 내장을 호출하거나 (miku의 예에서는) 특별한 처리가 진행되지 않습니다 true. 그것은 단지 문자열이며 완전히 임의적입니다.

업데이트 (2014-02-19) : miku의 답변에있는 링크를 따라 가면 혼란의 근원이 어디인지 알 수 있습니다. Miku의 답변은 단일 괄호를 사용하지만 그가 연결하는 코드 스 니펫은 괄호를 사용하지 않습니다. 그냥 :

the_world_is_flat=true
if $the_world_is_flat; then
  echo 'Be careful not to fall off!'
fi

두 코드 스 니펫은 동일한 방식으로 작동 하지만 괄호는 후드 아래에서 진행되는 작업을 완전히 변경합니다.

Bash가 각 경우에 수행하는 작업은 다음과 같습니다.

괄호 없음 :

  1. 변수 $the_world_is_flat를 문자열로 확장하십시오 "true".
  2. 문자열 "true"을 명령 으로 구문 분석하십시오 .
  3. true명령을 찾아 실행하십시오 (내장 또는 /bin/trueBash 버전에 따라).
  4. true명령 의 종료 코드 (항상 0 임)를 0과 비교하십시오. 대부분의 쉘에서 종료 코드 0은 성공을 나타내며 다른 것은 실패를 나타냅니다.
  5. 종료 코드가 0 (성공)이므로 if명령문의 then절을 실행하십시오 .

브래킷 :

  1. 변수 $the_world_is_flat를 문자열로 확장하십시오 "true".
  2. 이제 완전히 확장 된 조건식을 구문 분석하십시오 (이 형식은) string1 = string2. =연산자는 bash는의이다 문자열 비교 연산자입니다. 그래서…
  3. "true"및 에서 문자열 비교를 수행하십시오 "true".
  4. 그러나 두 문자열은 동일하므로 조건부 값이 참입니다.
  5. if명령문의 then절을 실행하십시오 .

true명령이 성공을 나타내는 종료 코드 0을 리턴 하므로 대괄호 없음 코드가 작동합니다 . 의 값이 의 오른쪽에있는 $the_world_is_flat문자열 리터럴과 동일 하므로 대괄호 코드가 작동 true합니다 =.

포인트를 집으로 몰아 가려면 다음 두 코드 조각을 고려하십시오.

이 코드 (루트 권한으로 실행되는 경우)는 컴퓨터를 재부팅합니다.

var=reboot
if $var; then
  echo 'Muahahaha! You are going down!'
fi

이 코드는 “Nice try”를 출력합니다. 재부팅 명령이 호출되지 않습니다.

var=reboot
if [ $var ]; then
  echo 'Nice try.'
fi

업데이트 (2014-04-14)===AFAIK 의 차이점에 대한 의견의 질문에 대답하면 차이 가 없습니다. ==운영자를위한 Bash 전용의 동의어 =, 그리고 지금까지 내가 본대로, 그들은 모든 상황에서 정확히 같은 작동합니다.

그러나 특히 테스트 또는 테스트에 사용되는 ===문자열 비교 연산자 에 대해 이야기 하고 있습니다 . 나는 그 제안 아니에요 과 교환 할 수있다 사방 bash는.[ ][[ ]]===

예를 들어, 당신은 분명히에 변수 할당 할 수없는 ==등, var=="foo"물론 기술적으로는 ( 이렇게, 그러나의 값이 var될 것입니다 "=foo"배쉬가 표시되지 않기 때문에, ==여기 연산자를, 그것은 보는 것 =다음에, (할당) 연산자를 리터럴 값 ="foo"은 단지)가됩니다 "=foo".

하지만 또한, ===상호 교환이 테스트 작업 방법, 당신이 있다는 사실을 숙지 않습니다 당신이 내부에 그것을 사용하고 있는지에 따라 [ ]또는 [[ ]],도에 피연산자가 인용 여부. Advanced Bash Scripting Guide : 7.3 Other Comparison Operators 에서 자세한 내용을 읽을 수 있습니다 ( =및 의 토론으로 스크롤 ==).


답변

산술 식을 사용하십시오.

#!/bin/bash

false=0
true=1

((false)) && echo false
((true)) && echo true
((!false)) && echo not false
((!true)) && echo not true

산출:

사실
거짓되지


답변

긴 이야기 요약 :

Bash에는 부울이 없습니다

Bash에는 비교 및 ​​조건 측면에서 부울식이 있습니다. Bash에서 선언하고 비교할 수있는 것은 문자열과 숫자입니다. 그게 다야.

Bash에서 true보거나 어디에 있든 false, 종료 코드에만 사용되는 문자열 또는 명령 / 내장입니다.

이 문법은 …

if true; then ...

본질적으로 …

if COMMAND; then ...

명령 반환 종료 코드 0 때마다 조건이 사실 true과는 false아무 만, 해당 종료 코드를 반환 할 없습니다 배쉬 내장 명령과 때로는 독립 프로그램입니다.

위의 조건은 다음과 같습니다.

COMMAND && ...

대괄호 나 test명령을 사용할 때는 해당 구문의 종료 코드를 사용합니다. 명심하십시오. 또한 다른 명령 [ ][[ ]]마찬가지로 명령 / 내장입니다. 그래서 …

if [[ 1 == 1 ]]; then echo yes; fi

에 해당

if COMMAND; then echo yes; fi

그리고 COMMAND여기에[[ 1 == 1 ]]

if..then..fi구조는 문법 설탕입니다. 동일한 효과를 위해 항상 이중 앰퍼샌드로 구분하여 명령을 실행할 수 있습니다.

[[ 1 == 1 ]] && echo yes

사용하는 경우 truefalse이러한 테스트 구조에 당신은 실제로 단지 문자열을 전달하는 "true"또는 "false"테스트 명령. 예를 들면 다음과 같습니다.

믿거 나 말거나 그러한 조건은 모두 같은 결과를 낳습니다 .

if [[ false ]]; then ...
if [[ "false" ]]; then ...
if [[ true ]]; then ...
if [[ "true" ]]; then ...

TL; DR; 항상 문자열이나 숫자와 비교

미래의 독자들에게이 명확하게하기 위해, 나는 주위에 따옴표를 사용하여 항상 추천 truefalse:

하다

if [[ "${var}" == "true" ]]; then ...
if [[ "${var}" == "false" ]]; then ...
if [[ -n "${var:-}" ]]; then echo "var is not empty" ...

하지마

if [ ... ]; then ...  # Always use double square brackets in bash!
if [[ "${var}" ]]; then ...  # This is not as clear or searchable as -n
if [[ "${var}" != true ]]; then ...  # Creates impression of Booleans
if [[ "${var}" -eq "true" ]]; then ...  # `-eq` is for numbers and doesn't read as easy as `==`

아마도

if [[ "${var}" != "true" ]]; then ...  # Creates impression of Booleans. It can be used for strict checking of dangerous operations. This condition is false for anything but the literal string "true".


답변

오래 전에, 우리가 가진 모든 것은 인수없이 실행되면 거짓 종료 상태를 반환하는 프로그램 sh의 규칙에 따라 처리되는 부울 입니다.testtest

이를 통해 거짓으로 설정되지 않은 변수를 true로 설정 한 변수를 생각할 수 있습니다. 오늘날 testBash에 내장되어 있으며 일반적으로 한 문자 별칭 [(또는 고인돌 메모가없는 쉘에서 사용할 수있는 실행 파일 )으로 알려져 있습니다.

FLAG="up or <set>"

if [ "$FLAG" ] ; then
    echo 'Is true'
else
    echo 'Is false'
fi

# Unset FLAG
#    also works
FLAG=

if [ "$FLAG" ] ; then
    echo 'Continues true'
else
    echo 'Turned false'
fi

인용 규칙으로 인해 스크립트 작성자는 [[모방 하는 복합 명령 을 선호 test하지만 구문이 더 좋습니다. 공백이있는 변수는 인용 할 필요가 없습니다. 하나는 사용할 수 &&||이상한 우선 순위 논리 연산자로, 그리고 용어의 수에는 POSIX 제한이 없습니다.

예를 들어 FLAG가 설정되어 있고 COUNT가 1보다 큰 숫자인지 확인하려면

FLAG="u p"
COUNT=3

if [[ $FLAG  && $COUNT -gt '1' ]] ; then
    echo 'Flag up, count bigger than 1'
else
    echo 'Nope'
fi

공백, 길이가 0 인 문자열 및 널 (null) 변수가 모두 필요한 경우와 스크립트가 여러 쉘에서 작동해야하는 경우에는 혼동수 있습니다 .


답변

쉘 스크립트에서 부울 변수를 어떻게 선언하고 사용할 수 있습니까?

다른 많은 프로그래밍 언어와 달리 Bash는 변수를 “유형”으로 분리하지 않습니다. [1]

답은 분명합니다. Bash 에는 부울 변수 가 없습니다 .

하나:

선언문을 사용하여 값 할당을 변수로 제한 할 수 있습니다. [2]

#!/bin/bash
declare -ir BOOL=(0 1) # Remember BOOL can't be unset till this shell terminates
readonly false=${BOOL[0]}
readonly true=${BOOL[1]}

# Same as declare -ir false=0 true=1
((true)) && echo "True"
((false)) && echo "False"
((!true)) && echo "Not True"
((!false)) && echo "Not false"

r의 옵션 declare과는 readonly변수가 명시 적으로 상태로 사용되는 읽기 전용 . 목적이 분명하기를 바랍니다.