bash [[]] 명령 내부의 자동 변수 확장 설명 할 수 있습니까? 편집

에서 변수를 역 참조 할 때는 부호 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)

    어디 st두 피연산자입니다. 피연산자는이 함수로 전달됩니다.

    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


답변

수치 비교 피연산자는 -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 ]] 

그리고 여기에서도 문자열 ( x6)이 비교됩니다.

x=6
[[ x = 6 ]]

이것은 변수를 확장시킬 것이기 때문에 사실입니다 :

x=6
[[ $x = 6 ]]


답변

예, 관측 값이 정확하고 이중 괄호 아래 표현식에서 변수 확장이 수행 [[ ]]되므로 따로 입력 할 필요가 없습니다.$ 변수 이름 앞에 .

bash매뉴얼에 명시되어 있습니다.

[[ 표현 ]]

(…) 단어 분리 및 경로 이름 확장은 [[와]] 사이의 단어에서 수행되지 않습니다. 물결표 확장, 매개 변수 및 변수 확장, 산술 확장, 명령 대체, 프로세스 대체 및 따옴표 제거가 수행됩니다.

이것은 쉘 키워드 (구문)가 아니라 명령 (단일 bash에서는 내장되어 있으며 다른 쉘은 외부를 사용하여 테스트 할 수 있음) [ ]과 같이 단일 브래킷 버전의 경우 [는 아닙니다.


답변