쿠살라난다와 시엔느의 토론을 보고 있어요여기, 이는 유효한 테스트가 아니며 [ "" -ge 2 ]
다른 POSIX 호환 셸에서 오류를 생성한다는 점을 언급합니다.bash --posix
bash-4.3$ [ "" -gt 10 ]
bash: [: : integer expression expected
bash-4.3$ [ '' -gt 10 ]
bash: [: : integer expression expected
거기 모든 것이 괜찮습니다. 호기심에 저도 똑같은 것을 시도해 보았습니다 [[
.
bash-4.3$ [[ "" -gt 10 ]] && echo "YES"
bash-4.3$ [[ "" -gt 0 ]] && echo "YES"
bash-4.3$ [[ "" -gt -1 ]] && echo "YES"
YES
bash-4.3$ [[ "" -eq 0 ]] && echo "YES"
YES
보시다시피 오류가 없으며 실제로 ""가 0인 숫자 표현식으로 평가됩니다. 그렇다면 여기서 정확히 무슨 일이 일어나고 있는 걸까요? [[
이전 또는 POSIX와 일치하지 않습니까 test
? 숫자 비교 대신 문자열 비교만 수행합니까?
답변1
[
와 의 한 가지 차이점은 다음과 같습니다 [[
.[
아니요산술 평가를 수행하지만 [[
:
$ [ "2 + 2" -eq 4 ] && echo yes
bash: [: 2 + 2: integer expression expected
$ [[ "2 + 2" -eq 4 ]] && echo yes
yes
두 번째 미묘함은 어디에서나산술 평가Bash에서 실행되면 빈 문자열은 0으로 평가됩니다. 예를 들어:
$ x=""; echo $((0 + x))
0
$ [[ "" -eq 0 ]] && echo yes
yes
문서
에서 man bash
:
쉘 변수는 피연산자로 허용됩니다. 표현식이 평가되기 전에 매개변수 확장이 수행됩니다. 표현식 내에서 쉘 변수는 매개변수 확장 구문을 사용하지 않고도 이름으로 참조될 수도 있습니다. null이거나 설정되지 않은 쉘 변수는 매개변수 확장 구문을 사용하지 않고 이름으로 참조할 때 0으로 평가됩니다. 변수가 참조되거나 -i 선언을 사용하여 정수 속성이 할당된 변수에 값이 할당되면 변수의 값은 산술 표현식으로 평가됩니다. Null 값은 0으로 평가됩니다.. 셸 변수는 정수 속성을 설정하지 않고도 표현식에서 사용할 수 있습니다. [강조 추가]
내레이터: 보안 문제
Bash의 산술 평가는 잠재적인 보안 문제입니다. 예를 들어 다음을 고려하십시오.
x='a[$(rm -i *)]'
[[ x -eq 0 ]] && echo yes
위의 작업은 이 -i
옵션을 사용하면 안전하지만 일반적인 교훈은 정리되지 않은 데이터에 대해 bash의 산술 평가를 사용하지 않는다는 것입니다.
대조적으로, 를 사용하면 [
산술 평가가 수행되지 않으므로 명령은 파일 삭제를 시도하지 않습니다. 대신 안전하게 오류가 발생합니다.
$ x='a[$(rm -i *)]'
$ [ "$x" -eq 0 ] && echo yes
bash: [: a[$(rm -i *)]: integer expression expected
이 문제에 대한 자세한 내용은 다음을 참조하세요.이 답변.
답변2
예, posix 테스트( [
)는 숫자 비교에서 문자열을 숫자로 변환하지 않습니다.
$ sh -c '[ 2+2 -eq 4 ]'
sh: 1: [: Illegal number: 2+2
$ dash -c '[ 2+2 -eq 4 ]'
dash: 1: [: Illegal number: 2+2
$ bash -c '[ 2+2 -eq 4 ] && echo "YES"'
bash: line 0: [: 2+2: integer expression expected
그러나 모든 쉘이 동일한 방식으로 작동하는 것은 아닙니다.
$ ksh -c '[ 2+2 -eq 4 ] && echo "YES"'
YES
일반적인 솔루션
null 또는 빈 값을 0으로 변환해야 합니다(대부분의 쉘에서 작동).
$ dash -c 'a=""; [ "${a:-0}" -gt 3 ] && echo "YES"'
산술 사용
산술 확장 사용( 2+2
일부 쉘에서와 같이 값(대시 아님)을 변환할 수도 있음)
$ dash -c 'a=""; [ "$((a+0))" -gt -3 ] && echo "YES"'
YES
사용[[
이 [[
테스트를 사용하면 이를 허용하는 쉘에서 숫자가 될 대부분의 문자열이 변환됩니다(필요하지 않더라도) [[
.
$ [[ "2+2" -gt 3 ]] && echo "YES"
YES