간단한 스크립트를 사용하고 싶습니다
flag=false
while !$flag
do
read x
if [ "$x" -eq "true" ]
then
flag=true
fi
echo "${x} : ${flag}"
done
그러나 그것을 실행할 때을 입력 true
하면 x="true"
및 을 볼 수 flag="true"
있지만주기는 끝나지 않습니다. 스크립트에 어떤 문제가 있습니까? 부울 변수를 올바르게 반전시키는 방법은 무엇입니까?
답변
스크립트에 두 가지 오류가 있습니다. 첫 번째는 당신이 사이의 공간이 필요하다 !
및 $flag
라는 명령, 그렇지 않으면 쉘 모습을 !$flag
. 두 번째 오류는 -eq
정수 비교에 관한 것이지만 문자열에서 사용하고 있습니다. 쉘에 따라 오류 메시지가 표시되고 조건을 충족 [ "$x" -eq "true" ]
할 수 없기 때문에 루프가 계속 지속 되거나 정수가 아닌 모든 값은 0으로 처리되며 문자열을 입력하면 루프가 종료됩니다 (포함 false
) 0과 다른 숫자 이외의
하지만 ! $flag
올바른, 그것은 명령으로 문자열을 처리하는 나쁜 생각입니다. 그것은 작동,하지만 당신이 있는지 확인해야 할 것입니다 이후는, 스크립트의 변화에 매우 민감 것 $flag
아무것도하지만, 결코 수 있습니다 true
또는 false
. 아래 테스트와 같이 여기에서 문자열 비교를 사용하는 것이 좋습니다.
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
답변
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 호환 쉘에서 작동하더라도 놀라지 않지만 표준을 확인하지는 않았습니다.
답변
변수에 0 또는 1이 포함될 것을 확실히 확신 할 수 있으면 비트 XOR- 등호 연산자를 사용하여 두 값 사이를 전환 할 수 있습니다.
$ foo=0
$ echo $foo
0
$ ((foo ^= 1))
$ echo $foo
1
$ ((foo ^= 1))
$echo $foo
0
답변
이것은 나를 위해 작동합니다 :
flag=false
while [[ "$flag" == "false" ]]
do
read x
if [[ "$x" == "true" ]]
then
flag=true
fi
echo "${x} : ${flag}"
done
그러나 실제로, 당신이해야 할 일은 다음으로 대체하는 것 while
입니다.
while ! $flag
답변
셸에는 부울 변수 개념이 없습니다.
쉘 변수는 될 수있는 text
경우에, 그 텍스트 (정수로 해석 할 수있다, (AN 문자열), 및 1
, 0xa
, 010
, 등).
따라서 flag=true
셸에 대한 진실성 또는 거짓이 전혀 없음을 의미합니다.
끈
수행 할 수있는 것은 문자열 비교 [ "$flag" == "true" ]
또는 일부 명령에서 변수 내용을 사용 하고 결과 와 같은 결과를 확인 하고 실행하십시오 true
(실행 파일 true
과 호출 파일이 모두 있기 때문에 false
) 명령으로 종료 명령이 0인지 확인하십시오 (성공한).
$flag; if [ "$?" -eq 0 ]; then ... fi
또는 더 짧게 :
if "$flag"; then ... fi
변수의 내용이 명령 !
으로 사용 ! cmd
되면 다음과 같이 ( ) 사이에 공백이 있으면 a를 사용하여 명령 의 종료 상태를 무효화 할 수 있습니다 .
if ! "$flag"; then ... fi
스크립트는 다음과 같이 변경되어야합니다.
flag=false
while ! "$flag"
do
read x
if [ "$x" == "true" ]
then
flag=true
fi
echo "${x} : ${flag}"
done
정수
숫자 값과 산술 확장을 사용하십시오 .
이 경우 종료 코드는 $((0))
is 1
이고 종료 코드는 $((1))
입니다 0
.
bash, ksh 및 zsh에서 산술은 내부에서 수행 될 수 있습니다 ((..))
(시작 $
이 누락 되었음을 유의하십시오 ).
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/ 에서 오류를 확인 하십시오 . 여러 번 문제를 찾기에 충분합니다.
답변
until
는 짧고 while !
( Bourne until
과 반대로 !
) 다음을 수행 할 수 있습니다.
flag=false
until "$flag"
do
IFS= read -r x
if [ "$x" = true ]
then
flag=true
fi
printf '%s\n' "$x : $flag"
done
다음과 동일해야합니다.
flag=false
while ! "$flag"
do
IFS= read -r x
if [ "$x" = true ]
then
flag=true
fi
printf '%s\n' "$x : $flag"
done
다음과 같이 쓸 수도 있습니다.
until
IFS= read -r x
printf '%s\n' "$x"
[ "$x" = true ]
do
continue
done
until
/ 사이 while
와 do
단일 명령 일 필요는 없습니다.
!
POSIX 쉘 구문의 키워드입니다. 그것은 구분되어야하고, 다음에 나오는 것과 분리 된 토큰이어야하고 파이프 라인 앞에 오는 첫 번째 토큰이어야합니다 ( ! foo | bar
파이프 라인을 foo | ! bar
무효화하고 일부 쉘이이를 확장으로 허용하더라도 유효하지 않습니다).
!true
!true
존재하지 않는 명령 으로 해석됩니다 . ! true
작동해야합니다. !(true)
그 같이 POSIX 호환 쉘에서 작동해야 !
그것이 다음 것으로 구분되어 (
토큰 있지만, 실제로는에 일을하지 않는 ksh
/ bash -O extglob
그것은과 충돌 곳 !(pattern)
이 충돌하는 곳 (SH 에뮬레이션 제외) 확장 글로브 운영자 나 zsh을 glob(qualifiers)
가진 bareglobqual
및 glob(group)
없이.
답변
[ ${FOO:-0} == 0 ] && FOO=1 || FOO=0
또는:
[ ${FOO:-false} == false ] && FOO=true || FOO=false
일을해야한다