bash는 삼중 괄호를 어떻게 해석합니까?

bash는 삼중 괄호를 어떻게 해석합니까?

Bash에서 명령을 봅니다.

echo $(((i=18)))

18을 인쇄하세요. 이것은 $(((i=18)))가 산술 확장으로 해석된다는 것을 이해하게 해줍니다(변수 i는 생성자 내부에서 초기화됩니다). 그러나 명령 대체를 고려할 수도 있습니다.

$(command)

그리고

((i=18))

command, 실제로는 명령 대체가 나올 것 같습니다.앞으로산술 확장(bash 쉘 배우기, 오라일리 2005, 17페이지. 181). 따라서 결과는 기대했던 것과 다릅니다. 이것을 어떻게 설명합니까?

답변1

와트. $(((i=18))), 당신 말이 맞습니다. $(( (i=18) )), 또는 $( ((i=18)) )둘 다 유효합니다. 다소 일반적입니다(확실히단순한) 이러한 모호한 상황을 설명하는 방법은 가장 긴 유효한 연산자를 식별하는 것입니다. 이는 가 $((뒤에 오는 것으로 해석된다는 의미입니다 (.

예를 들어 Bash와 Ksh에서 일어나는 일은 다음과 같습니다 <<(. <<뒤에는 가 있지만 뒤에는 (가 없습니다 .<<(첫 번째 설명은 문법 오류이지만 두 번째 설명은 유효합니다!사용자는 쉘이 찾을 수 있도록 공백을 추가해야 합니다. 마찬가지로, i+++a그렇습니다 . i++ + a그리고 아니오 i + ++a. 다른 언어에도 비슷한 상황이 존재합니다.

그러나 의 경우 $(((이는 전적으로 사실이 아닙니다. 일부 껍질은 더 멀리 떨어져 있는 것처럼 보이지만 일부는 그렇지 않습니다. 예를 들어 다음을 고려하십시오.

echo $((echo hi); (echo ho))

명령 대체로 해석하면 유효하며 을 인쇄합니다 hi ho. 그러나 탐욕스러운 인식은 $((이를 산술 확장으로 해석하므로 완전히 거짓입니다.

Dash와 Busybox를 제외하고 내가 시도한 모든 쉘은 유효한 명령 대체를 인식합니다. 처음 두 괄호 사이에 공백을 넣으면 명확해집니다.

실제로 연산 확장 이전에 명령 대체가 발생하는 것처럼 보입니다.

아니요, 동일한 처리 지점에서 발생합니다. 이를 확인하려면 유효한 산술 확장으로 확장되는 명령 대체를 만듭니다. 예를 들어 echo '$((1+2))'print $((1+2)); $( echo '$((1+2))' )로 확장되지만 $((1+2))동일한 명령에서는 더 이상 처리되지 않습니다.

이것,

echo $( echo '$((1+2))' )

$((1+2))대신 출력합니다 3.

물론 산술 확장은 숫자만 생성할 수 있으므로 역순은 테스트할 수 없습니다. 그러나 변수/인수 확장과 명령 대체 간에 유사한 실험을 수행할 수 있으며 어떤 경우에도 한 번의 확장 결과는 더 이상 확장되지 않습니다.


지원 확장, 반면에 그것은 다릅니다.

Bash는 변수가 확장되기 전에 변수를 처리합니다.

$ bash -c 'v=000 va=123 vb=456; echo $v{a,b}; n=1 m=4; echo {$n..$m}'
123 456
{1..4}

Ksh의 경우에는 그 반대입니다.

$ ksh -c 'v=000 va=123 vb=456; echo $v{a,b}; n=1 m=4; echo {$n..$m}'
000a 000b
1 2 3 4

(Ksh에서는 a="{1.."; b="4}"; echo $a$b중괄호도 확장되어 인쇄됩니다 1 2 3 4. Zsh는 여기서도 제정신이므로 변수를 먼저 확장하지만 확장된 중괄호가 추가 확장을 트리거하도록 허용하지 않습니다. Zsh 도 <<(이를 인식합니다 < <(.)

물론 있습니다.분사및 파일 이름 생성, 여기서발생하다결국, 결과만을 위해서인용되지 않음확대.

답변2

이 동작은 다음에 설명된 것과 일치합니다.배쉬 변경 파일:

$((...))Posix에서 요구하는 대로 잠재적으로 중첩된 명령 대체보다는 항상 산술 확장을 먼저 해결합니다.

물론,POSIX가 인식됨모호한 점이 있으면 산술 확장이 우선해야 합니다.

쉘 명령 언어의 구문은 $((" "로 시작하는 확장에 대해 모호합니다. 이는 하위 쉘로 시작하는 산술 확장이나 명령 대체를 도입할 수 있습니다.산술 확장이 우선합니다.;즉, 쉘은 확장을 산술 확장으로 해결할 수 있는지 먼저 결정해야 하며, 확장을 산술 확장으로 해결할 수 없다고 판단하면 확장을 명령 대체로만 해결해야 합니다.

이제 문장의 일부 단어 "산술 확장 앞에 명령 대체가 오는 것 같습니다.": 아니요,POSIX 지정단어 확장은 처음부터 끝까지, 즉 나타나는 순서대로 왼쪽에서 오른쪽으로 발생합니다.

물결표 확장, 매개변수 확장, 명령 대체 및 산술 확장은 처음부터 끝까지 수행되어야 합니다.

이것"토큰 인식" 섹션몇 가지 추가 정밀도가 제공됩니다.

현재 문자가 따옴표가 없는 '$' 또는 '``'인 경우 쉘은 따옴표가 없는 소개 문자 시퀀스인 '$' 또는 " ${"에서 매개변수 확장, 명령 대체 또는 산술 확장에 대한 후보의 시작을 식별해야 합니다. , 또는 "$(" 또는 "`" 및 "$((" 각각. 쉘은 확장할 장치의 끝을 결정하기 위해 충분한 입력을 읽어야 합니다.

관련 정보