끈

간단한 스크립트를 사용해 보고 싶습니다.

flag=false
while !$flag
do
   read x
   if [ "$x" -eq "true" ]
   then
     flag=true
   fi
   echo "${x} : ${flag}"
done

그런데 실행할 때 를 입력하면 and가 true표시되지만 루프가 끝나지 않습니다. 스크립트에 어떤 문제가 있나요? 부울 변수를 올바르게 반전시키는 방법은 무엇입니까?x="true"flag="true"

답변1

스크립트에 두 가지 오류가 있습니다. 첫 번째는 !과 사이에 공백이 있어야 한다는 것입니다 $flag. 그렇지 않으면 쉘은 이라는 명령을 찾습니다 !$flag. 두 번째 오류는 -eq정수 비교를 위한 것이지만 문자열에 사용하고 있습니다. 쉘에 따라 오류 메시지가 표시될 수 있으며 조건이 true가 될 수 없거나 정수가 아닌 모든 값이 0으로 처리되기 때문에 루프가 영원히 계속됩니다. 를 포함한 문자열을 입력하면 [ "$x" -eq "true" ]루프가 false다음이 아닌 숫자로 종료됩니다. 0.

이것이 맞기 는 하지만 ! $flag문자열을 명령으로 취급하는 것은 좋지 않습니다. 작동하지만 스크립트의 변경 사항에 매우 민감합니다. 또는 이외의 것이 $flag아닌지 확인해야 하기 때문입니다 . 여기서는 아래 테스트처럼 문자열 비교를 사용하는 것이 더 좋습니다.truefalse

flag=false
while [ "$flag" != "true" ]
do
   read x
   if [ "$x" = "true" ]
   then
     flag=true
   fi
   echo "${x} : ${flag}"
done

당신이 추구하는 논리를 표현하는 더 좋은 방법이 있을 것입니다. 예를 들어 무한 루프를 생성하고 종료 조건이 감지되면 이를 중단할 수 있습니다.

while true; do
  read -r x
  if [ "$x" = "true" ]; then break; fi
  echo "$x: false"
done

답변2

Bash에는 부울 변수가 없지만 산술 평가를 사용하여 이를 에뮬레이트하는 것은 매우 쉽습니다.

flag= # False
flag=0 # False
flag=1 # True (actually any integer number != 0 will do, but see remark below about toggling)
flag="some string" # Maybe False (make sure that the string isn't interpreted as a number)

if ((flag)) # Test for True
then
  : # do something
fi

if ! ((flag)) # Test for False
then
  : # do something
fi

flag=$((1-flag)) # Toggle flag (only works when flag is either empty or unset, 0, 1, or a string which doesn't represent a number)

이것은 ksh에서도 작동합니다. 모든 POSIX 호환 쉘에서 작동하더라도 놀라지 않을 것입니다. 그러나 아직 표준을 확인하지 않았습니다.

답변3

변수에 0이나 1이 포함될 것이라고 확신하는 경우 비트 XOR 등호 연산자를 사용하여 두 값 사이를 전환할 수 있습니다.

$ foo=0
$ echo $foo
0
$ ((foo ^= 1))
$ echo $foo
1
$ ((foo ^= 1))
$echo $foo
0

답변4

쉘에는 부울 변수 개념이 없습니다.
쉘 변수는 (문자열)만 가능하며 text어떤 경우에는 텍스트가 정수( 1, 0xa010)로 해석될 수 있습니다.

따라서 a는 flag=true쉘에 대해 참 또는 거짓을 전혀 의미하지 않습니다.

수행할 수 있는 작업은 문자열 비교 [ "$flag" == "true" ]또는 일부 명령에서 변수 내용을 사용하여 확인하는 것입니다.그 결과, 명령으로 실행 (이름이 지정된 실행 파일 과 이름이 지정된 실행 파일이 true모두 있으므로 )하고 해당 명령의 종료 코드가 0(성공)인지 확인하는 것과 같습니다.truefalse

$flag; if [ "$?" -eq 0 ]; then ... fi

또는 더 짧게:

if "$flag"; then ... fi

변수의 내용이 명령으로 사용되는 경우 다음과 같이 둘 사이에 공백( )이 있으면 a를 !사용하여 명령의 종료 상태를 무효화할 수 있습니다.! cmd

if ! "$flag"; then ... fi

스크립트는 다음과 같이 변경되어야 합니다.

flag=false
while ! "$flag" 
do
   read x
   if [ "$x" == "true" ]
   then
     flag=true
   fi
   echo "${x} : ${flag}"
done

정수

숫자와산술 확장.

이 경우의 종료 코드 $((0))는 이고 1, 종료 코드는 $((1))입니다 0.
bash, ksh 및 zsh에서는 a 내에서 산술을 수행할 수 있습니다( ((..))시작 부분이 없음에 주의).$

flag=0; if ((flag)); then ... fi

이 코드의 이식 가능한 버전은 더 복잡합니다.

flag=0; if [ "$((flag))" -eq 0 ]; then ... fi      # test for a number
flag=0; if [ "$((flag))"  == 0 ]; then ... fi      # test for the string "0"

bash/ksh/zsh에서는 다음을 수행할 수 있습니다.

flag=0    
while ((!flag)) 
do
   read x
   [ "$x" == "true" ] && flag=1
   echo "${x} : ${flag}"
done

또는

"부울 변수를 반전"할 수 있습니다(숫자 값이 포함된 경우).

((flag=!flag))

그럴 것이다변화flag또는 0가치 1.


노트: 오류가 있는지 확인해주세요.https://www.shellcheck.net/많은 경우 이는 코드를 이슈로 게시하기 전에 문제를 찾는 데 충분합니다.

관련 정보