bash test
또는 내장 명령을 사용하여 [
논리적 NOT을 사용하여 조건식을 평가할 때 !
느낌표를 대괄호 내부에 배치해야 합니까, 아니면 외부에 배치해야 합니까? 그게 그렇게 중요한 건가?
이것은 간단한 MRE입니다.
$ var=1
$ if [ $var -gt 0 ]; then echo "evaluated to true"; else echo "evaluated to false"; fi
evaluated to true
$ if ! [ $var -gt 0 ]; then echo "evaluated to true"; else echo "evaluated to false"; fi
evaluated to false
$ if [ ! $var -gt 0 ]; then echo "evaluated to true"; else echo "evaluated to false"; fi
답변1
! [ "$var" -gt 0 ]
[ ! "$var" -gt 0 ]
오류가 없는 한 현재 쉘과 유틸리티는 중요하지 않습니다.
하지만 따옴표 if ! [ $var -gt 0 ]
없이 썼다는 점에 유의하세요.if [ ! $var -gt 0 ]
$var
정말 중요한!
$var
비어 있거나 공백이 포함되어 있으면 중단됩니다. 예를 들어 다음과 같은 내용이 표시됩니다 if ! [ -gt 0 ]
. 테스트에서 [
오류 메시지가 인쇄되고 잘못된 종료 코드 2가 반환됩니다. 그러면 반전되어 !
전체 조건이 참이 됩니다!
$ var=
$ if ! [ $var -gt 0 ]; then echo yes; fi
bash: [: -gt: unary operator expected
yes
특정 상황에서는 [ ! $var -gt 0 ]
거짓 오류 반환이 거짓으로 유지되고 분기가 수행되지 않으므로 더 안전한 것으로 간주될 수 있습니다. 그러나 여기서 가장 즉각적인 문제는 쉽게 고칠 수 있는 따옴표가 없다는 것입니다.
견적은 다음을 참조하세요.언제 큰따옴표가 필요합니까?
그러나 인용 문제와 별개로 에 숫자가 아닌 값이 있으면 $var
오류가 발생 [
하고 조건이 거짓이 됩니다. 따라서 입력이 유효한지 미리 테스트하거나 이 가능성을 처리해야 합니다. 경우에 따라 오류가 발생했을 때 올바른 조치는 다음과 같습니다.가져가다예를 들어, 오류 종료가 포함된 경우 분기입니다. 불행하게도 쉘에는 예외 등이 없기 때문에 실제로 오류를 감지하는 좋은 방법이 없습니다. 오류와 잘못된 결과를 구별하려면 $?
원래 값을 저장하고 참조해야 합니다.
또는 오류 조건이 적절한 결과와 일치하도록 테스트를 작성할 수 있습니다. 예를 들어 여기 테스트는 대신 추가 부정을 사용하여 작성되었지만 [ "$1" -le 0 ]
잘못된 입력으로 인해 오류 종료가 발생한다는 이점이 있습니다. 이것은 !
외부에서만 작동합니다 [
.
$ cat foo.sh
#!/bin/bash
if ! [ "$1" -gt 0 ]; then
echo "invalid input '$1'"
exit 1
fi
echo "doing work on '$1'"
$ bash foo.sh
foo.sh: line 3: [: : integer expression expected
invalid input ''
변수 값의 변경 및 매트릭스의 다양한 테스트:
테스트\$n | '0' '1' 'x' ------+------------------ -- ---- [“$n”-le 0] |참 또는 거짓(오류 있음) [! "$n"-gt 0] | true false false(오류 있음) ! [“$n”-gt 0] |참 또는 거짓 참(오류 있음)
아마도 과거에 [
테스트의 피연산자가 연산자처럼 보일 때 혼동을 주었던 버전과 다소 관련이 있을 수 있습니다. 예를 들어, [ ! = x ]
the와 같은 것은 !
부정으로 처리될 수 있으며 전체 표현식을 구문 분석할 수 없습니다. !
내부에 넣는 것이 [
문제를 복잡하게 만들지 않을까 걱정할 수도 있지만 실제로 그런 일이 일어날지는 모르겠습니다. 그럼에도 불구하고 POSIX 호환 버전 은 [
적어도 .-a
-o
바라보다:쉘 변수를 문자열 리터럴과 비교할 때 양쪽에 접두사를 추가하는 목적은 무엇입니까?, 특히 Stéphane의 탁월한 답변(이 예를 사용했습니다 [ ! = x ]
).
답변2
예, 그것은 중요합니다.
!
외부에 배치하면 [ ... ]
모든 오류가 무시됩니다.
var=nono
if ! [ "$var" -gt 0 ]; then echo YES; fi
bash: [: 0.1: integer expression expected
YES
if [ ! "$var" -gt 0 ]; then echo YES; fi
bash: [: 0.1: integer expression expected
if ! command; then ...
이는 종료 상태가 0이 아닌 경우 일치가 발생하고 명령은 command
오류 시 및 false 로 평가되는 경우 [ expr ]
모두 0이 아닌 종료 상태를 갖기 때문입니다 .expr
bash가 아닌 ksh에서만 두 가지가 유사합니다. ksh에서는 숫자가 아닌 변수가 0
해당 컨텍스트에서 오류가 아닌 변수로 처리되기 때문입니다.
답변3
평가 대상에 관심이 있는 경우에만 중요합니다 . 유틸리티의 오류를 고려 !
하면 수행할 수 있습니다 (예: 실제로 정수가 아닌 경우 유틸리티가 실패하고 종료 상태가 0이 아님). 테스트는 다음과 같이 평가됩니다.[
$var
[
잘못된그러나 유틸리티가 테스트를 실행하지 못했기 때문입니다.)
in 은 if [ ! "$var" -gt 0 ]; then ...; fi
인수 !
이므로 [
유틸리티에 의해 평가되어 [
적절한 종료 상태로 종료되기 전에 테스트의 의미를 내부적으로 무효화합니다. ( $var
정수가 아닌 경우 테스트가 실패하고 분기가 수행되지 않습니다.)
에서 쉘은 if ! [ "$var" -gt 0 ]; then ...; fi
명령문에 유틸리티를 사용하기 전에 유틸리티의 종료 상태를 억제합니다(0과 0이 아닌 값 사이에서 전환). (정수가 아닌 경우 테스트는 실패하고 쉘은 0이 아닌 종료 상태를 무효화하고 다음과 같이 해석합니다.[
if
$var
진짜, 지점이 채택됩니다. )
이 간단한 테스트의 경우 코드를 더 쉽게 읽고 이해할 수 있도록 테스트를 다시 작성하고 [ "$var" -le 0 ]
필요한 경우 $var
정수 유효성 검사를 사용합니다.