이것은 테스트 [
내장이 정의 되는 방식에서 버그를 고려할 수있는 매우 모호한 경우입니다 . 그러나 [
많은 시스템에서 사용 가능한 실제 바이너리 의 동작과 일치합니다 . 지금까지 내가 말할 수있는, 그것은 특정의 경우와 일치하는 값을 갖는 변수에 영향을 미치는 [
같은 연산자를 (
, !
, =
, -e
, 등을.
Bash와 POSIX 쉘에서 그 이유와 그 해결 방법을 설명하겠습니다.
설명:
다음을 고려하세요:
x="("
[ "$x" = "(" ] && echo yes || echo no
문제 없어; 위의 오류는 발생하지 않으며 출력 yes
합니다. 이것이 우리가 일을 기대하는 방법입니다. 원하는 '1'
경우 비교 문자열 과의 값을 변경할 수 있으며 x
예상대로 작동합니다.
실제 /usr/bin/[
바이너리는 같은 방식으로 작동합니다. 예를 들어 '/usr/bin/[' '(' = '(' ']'
프로그램을 실행하면 인수가 단일 문자열 비교 작업으로 구성되어 있음을 감지 할 수 있으므로 오류가 없습니다.
우리 와 두 번째 표현을 할 때 버그가 발생합니다 . 유효한 두 번째 표현식은 중요하지 않습니다. 예를 들어
[ '1' = '1' ] && echo yes || echo no
outputs yes
이며 분명히 유효한 표현식입니다. 하지만 둘을 결합하면
[ "$x" = "(" -a '1' = '1' ] && echo yes || echo no
Bash x
는 is (
또는 경우에만 표현식을 거부합니다 !
.
우리가 실제 [
프로그램을 사용하여 위를 실행한다면 , 즉
'/usr/bin/[' "$x" = "(" -a '1' = '1' ] && echo yes || echo no
에러는 이해할 것이다 : 쉘 변수 치환을 수행하기 때문에, /usr/bin/[
이진은 파라미터를 수신 (
=
(
-a
1
=
1
하고, 종단에서는 ]
이 생길되는 열린 괄호 하위 표현식을 시작 여부는 당연히 해석에 실패 여부 와 관련된 동작. 물론 두 문자열 비교로 구문 분석하는 것이 가능하지만 욕심이 많은 하위 표현식이있는 적절한 표현식에 적용될 때 문제가 발생할 수 있습니다.
실제로 문제는 셸 [
내장 x
이 표현식을 검사하기 전에 값을 확장 한 것처럼 동일한 방식으로 작동 한다는 것입니다.
(이러한 모호함과 변수 확장과 관련된 다른 것들은 Bash가 구현 된 큰 이유였으며 이제 [[ ... ]]
대신 테스트 표현식 사용을 권장 합니다.)
이 해결 방법은 사소한 것이며 종종 오래된 sh
쉘을 사용하는 스크립트에서 볼 수 있습니다. x
표현식이 문자열 비교로 인식되도록하기 위해 종종 문자열 앞에 "안전한"문자를 추가합니다 (두 값 모두 비교됨).
[ "x$x" = "x(" -a "x$y" = "x1" ]
[[ "$x" = '1' && "$y" = '1' ]]