에서 변수를 역 참조 할 때는 부호 bash
를 사용해야 $
합니다. 그럼에도 불구하고 다음이 제대로 작동하는 것 같습니다.
x=5
[[ x -gt 2 ]]
아무도 이것을 설명 할 수 있습니까?
편집 : (추가 정보)
내 말은 [[]] 명령이 $ 기호없이 변수 x를 역 참조하는 방법과 이유입니다. 그리고 그렇습니다. x = 1이면, 문장은 거짓으로 평가됩니다 (반환 상태 1).
에서 변수를 역 참조 할 때는 부호 bash
를 사용해야 $
합니다. 그럼에도 불구하고 다음이 제대로 작동하는 것 같습니다.
x=5
[[ x -gt 2 ]]
아무도 이것을 설명 할 수 있습니까?
편집 : (추가 정보)
내 말은 [[]] 명령이 $ 기호없이 변수 x를 역 참조하는 방법과 이유입니다. 그리고 그렇습니다. x = 1이면, 문장은 거짓으로 평가됩니다 (반환 상태 1).
답변:
그 이유는 -eq
인수의 산술 평가를 강제하기 때문입니다 .
산술 연산자 : -eq
, -gt
, -lt
, -ge
, -le
및 -ne
돌며 [[ ]]
(KSH에서 zsh을 배시) 자동 C 언어로 변수 이름을 확장 수단 선두 위해 필요하지 $
.
확인을 위해 bash 소스 코드를 살펴 봐야합니다. 매뉴얼은 직접 확인 하지 않습니다 .
test.c
산술 연산자의 처리 내부 에는이 함수가 포함됩니다.
arithcomp (s, t, op, flags)
어디 s
와 t
두 피연산자입니다. 피연산자는이 함수로 전달됩니다.
l = evalexp (s, &expok);
r = evalexp (t, &expok);
이 함수 evalexp
는 내부 expr.c
에 정의되어 있으며이 헤더는 다음과 같습니다.
/* expr.c -- arithmetic expression evaluation. */
그래서, 산술 연산자의 양쪽은 (직접적으로) 산술 표현 평가에 빠지게됩니다. 직접, 엉덩이도없고, if도 없습니다.
실제로,
$ x=3
이 두 가지 모두 실패합니다.
$ [[ x = 4 ]] && echo yes || echo no
no
$ [[ x = 3 ]] && echo yes || echo no
no
어느 것이 정확 x
하고 확장 x
되지 않고 숫자 와 같지 않습니다.
하나:
$ [[ x -eq 3 ]] && echo yes || echo no
yes
$ [[ x -eq 4 ]] && echo yes || echo no
no
이름 x
이 붙은 변수 는 $없이 확장됩니다.
이것은 […]
zsh 또는 bash (ksh에서)에서 발생하지 않습니다 .
그것은 내부에서 일어나는 것과 동일합니다 $((…))
:
$ echo $(( x + 7 ))
10
그리고 이것이 (매우) 재귀 적이라는 것을 이해하십시오 (대시 및 야쉬 제외).
$ a=b b=c c=d d=e e=f f=3
$ echo "$(( a + 7 ))"
10
그리고 매우 위험합니다 :
$ x='a[$(date -u)]'
$ [[ x -eq 3 ]] && echo yes || echo no
bash: Tue Dec 3 23:18:19 UTC 2018: syntax error in expression (error token is "Dec 3 23:18:19 UTC 2018")
구문 오류는 쉽게 피할 수 있습니다.
$ a=3; x='a[$(date -u >/dev/tty; echo 0)]'
$ [[ x -eq 3 ]] && echo yes || echo no
Tue Dec 4 09:02:06 UTC 2018
yes
말대로 : 입력을 소독하십시오
$ [[ ${x//[^0-9]} -eq 3 ]] && echo yes || echo no
no
😮의 끝
(오래된) 외부 /usr/bin/test
(내장되지 않음 test
)와 더 오래되고 외부 expr
는 모두 표현식 만 정수 (및 분명히 십진 정수 만)를 확장하지 않습니다 .
$ /usr/bin/test "x" -eq 3
/usr/bin/test: invalid integer ‘x’
$ expr x + 3
expr: non-integer argument
[[
키워드, 연산자 및 피연산자는 확장 후가 아니라 명령을 읽을 때 감지됩니다. 따라서 보다 더 현명한 방법으로 [[
치료할 수 있습니다 . 그러나 내가 궁금한 점은 복합 명령을 해석하기 위해 bash가 사용하는 논리에 대한 문서를 어디에서 찾을 수 있습니까? 그것은 나에게 분명하게 보이지 않으며 또는 에서 만족스러운 설명을 찾을 수없는 것 같습니다 . -eq
[
man
info bash
test
수치 비교 피연산자는 -eq
, -gt
, -lt
, -ge
, -le
및 -ne
연산 식으로 수행된다. 약간의 제한이 있지만, 여전히 단일 쉘 단어 여야합니다.
산술 표현식에서 변수 이름의 동작은 셸 산술에 설명되어 있습니다 .
쉘 변수는 피연산자로 허용됩니다. 표현식이 평가되기 전에 매개 변수 확장이 수행됩니다. 표현식 내에서 매개 변수 확장 구문을 사용하지 않고 쉘 변수를 이름으로 참조 할 수도 있습니다. 매개 변수 확장 구문을 사용하지 않고 이름으로 참조 할 때 널이거나 설정되지 않은 쉘 변수는 0으로 평가됩니다.
그리고 또한:
변수의 값은 참조 될 때 산술 표현식으로 평가됩니다
그러나 실제로 숫자 비교에는 산술 연산식이 필요하다는 문서의 일부를 찾을 수 없습니다. 그것은 설명 아니에요 조건부 구축해 에서 [[
않으며에서 설명 배쉬 조건식 .
그러나 실험적으로는 위에서 말한 것처럼 작동하는 것 같습니다.
따라서 다음과 같은 것들이 작동합니다.
a=6
[[ a -eq 6 ]] && echo y
[[ 1+2+3 -eq 6 ]] && echo y
[[ "1 + 2 + 3" -eq 6 ]] && echo y
이것도 (변수의 값이 평가됩니다) :
b='1 + 2 + 3'
[[ b -eq 6 ]] && echo y
그러나 이것은 그렇지 않습니다. [[ .. ]]
구문 분석 할 때 단일 쉘 단어 가 아니므로 조건부에서 구문 오류가 있습니다.
[[ 1 + 2 + 3 -eq 6 ]] && echo y
다른 산술 컨텍스트에서는 표현식에 공백이 없어도됩니다. 999
대괄호가 인덱스의 산술 표현식을 명확하게 구분하기 때문에을 인쇄합니다 .
a[6]=999; echo ${a[1 + 2 + 3]}
다른 한편으로, =
비교는 패턴 일치 이며, 산술 또는 산술 컨텍스트에서 수행 된 자동 변수 확장 (조건부 구성)을 포함하지 않습니다.
경우
==
와!=
사업자가 사용하는 extglob 쉘 옵션을 사용하는 것처럼, 작업자의 오른쪽에있는 문자열 패턴 매칭에 설명 된 규칙에 따른 패턴에 일치 간주된다.=
오퍼레이터는 동일하다==
.
따라서 문자열이 분명히 다르기 때문에 이것은 거짓입니다.
[[ "1 + 2 + 3" = 6 ]]
숫자 값이 동일하더라도 다음과 같습니다.
[[ 6 = 06 ]]
그리고 여기에서도 문자열 ( x
과 6
)이 비교됩니다.
x=6
[[ x = 6 ]]
이것은 변수를 확장시킬 것이기 때문에 사실입니다 :
x=6
[[ $x = 6 ]]
arg1 OP arg2
args가 양 또는 음의 정수 일 수 있다고 설명하는 것으로, 산술 표현식으로 취급된다는 것을 암시한다고 생각합니다. 혼란스럽게도 0이 될 수 없음을 의미합니다. :)
[
산술 표현식이 아닙니다. 대신 Bash는 비정 수에 대해 불평합니다.
[
는 외부 명령이며 쉘 변수에 액세스 할 수 없습니다. 종종 내장 명령으로 최적화되지만 여전히 동일하게 동작합니다.
예, 관측 값이 정확하고 이중 괄호 아래 표현식에서 변수 확장이 수행 [[ ]]
되므로 따로 입력 할 필요가 없습니다.$
변수 이름 앞에 .
bash
매뉴얼에 명시되어 있습니다.
[[ 표현 ]]
(...) 단어 분리 및 경로 이름 확장은 [[와]] 사이의 단어에서 수행되지 않습니다. 물결표 확장, 매개 변수 및 변수 확장, 산술 확장, 명령 대체, 프로세스 대체 및 따옴표 제거가 수행됩니다.
이것은 쉘 키워드 (구문)가 아니라 명령 (단일 bash에서는 내장되어 있으며 다른 쉘은 외부를 사용하여 테스트 할 수 있음) [ ]
과 같이 단일 브래킷 버전의 경우 [
는 아닙니다.
(x=1; [[ $x = 1 ]]; echo $?)
returns 0
, (x=1; [[ x = 1 ]]; echo $?)
returns 1
, 즉 x
문자열을 비교할 때 매개 변수 확장이 수행되지 않습니다 . 이 동작은 산술 확장에 의해 트리거되는 산술 평가, 즉에서 발생하는 것처럼 보입니다 (x=1; echo $((x+1)))
. (산술 평가에 man bash
대해서는 "표현식 내에서 매개 변수 확장 구문을 사용하지 않고 쉘 변수를 이름으로 참조 할 수도 있습니다")
-gt
연산자는 숫자를 기대하므로 전체 표현식은 마치 마치 내부처럼 다시 평가되고 (())
, 반면 ==
문자열은 문자열 일치를 기대하므로 패턴 일치 함수가 트리거됩니다. 소스 코드를 파헤 치지 않았지만 합리적으로 들립니다.
[
bash에 내장 된 쉘입니다.
x=1
다음에 평가가 변경[[ x -gt 2]]
됩니까?