Bash: 산술 확장, 매개변수 확장 및 쉼표 연산자

Bash: 산술 확장, 매개변수 확장 및 쉼표 연산자

산술 표현식 내에서 쉼표 표현식 내부의 bash 매개변수 확장에 대한 질문이 있습니다. 나는 동등해야 한다고 생각했지만 그렇지 않은 두 가지 진술을 가지고 있습니다.

왜 bash 라인은

n=3; k=10; echo $((n++,k=$n))

3대신에 출력 4? ( 예상대로 로 설정되어 있는데 로 설정되어 n있습니다 . )4k3

대조적으로, bash 라인은

 n=3; k=10; echo $((n++,k=n))

4예상대로 출력됩니다 . ( , n로 설정 됩니다 .)4k4

n++나는 두 bash 줄에서 with ++n, with n=n+1및 with 를 바꾸려고 시도했지만 n=$((n+1))모두 동일한 불일치를 나타냅니다. 모든 스크립트에서 k=$n생성되고 모든 스크립트에서 생성됩니다 .3k=n4


내 이해는 값이 n정수(정수) 인 경우 산술 표현식 내에서 동일한 값을 가져야 한다는 것입니다 $n. n(그리고 이것은 구조 때문에 산술 표현식입니다 (( ... )).) bash 매뉴얼에 따르면 산술 평가 섹션의 산술 표현식에서:

   Shell variables are allowed as  operands;  parameter  expansion  is  performed  before  the
   expression  is  evaluated.  Within an expression, shell variables may also be referenced by
   name without using the parameter expansion syntax.

그렇다면 bash가 이 예 $n와 다르게 처리하는 이유는 무엇 n이며 정확히 어떻게 평가합니까 $n?


쉼표 연산자를 사용하지 않고는 문제를 복제할 수 없습니다. 내가 항상 보아온 쉼표 연산자는 해당 구성 요소가 계산될 때 각 구성 요소의 모든 부작용을 포함하여 왼쪽에서 오른쪽으로 각 구성 요소 하위 표현식을 계산합니다. 쉼표 표현식의 값은 계산된 마지막 구성 요소(가장 오른쪽 구성 요소)의 값입니다.


이 질문은 훨씬 더 복잡한 스크립트의 맥락에서 발생했으며 마침내 문제를 보여주는 이 간단한 예제로 범위를 좁혔습니다.

그렇다면 산술 확장, 매개변수 확장 또는 쉼표 연산자에 대해 내가 무엇을 오해하고 있습니까?

이미 해결 방법이 있으므로 해결 방법을 찾고 있는 것이 아닙니다. n대신 에 버전이 $n예상대로 작동합니다. 나는 bash가 가 있는 버전에서 무엇을 하고 있는지 $n, 왜 bash가 단지 가 있는 버전과 다른 일을 하는지 알고 싶습니다 n.

답변1

쉘 매개변수 확장이 발생합니다.쉼표 처리를 포함하여 표현식이 평가되기 전:

표현식은 큰따옴표 안에 있는 것처럼 처리되지만, 괄호 안의 큰따옴표는 특별히 처리되지 않습니다. 표현식의 모든 토큰은 매개변수 및 변수 확장, 명령 대체 및 따옴표 제거를 거칩니다. 결과는 평가할 산술 표현식으로 처리됩니다.

당신은 이것을 볼 수 있습니다

unset n
echo $((n++,k=$n))

오류 메시지는,

bash: n++,k=: syntax error: operand expected (error token is "=")

$n전체 산술식이 처리되기 전에 대체되는 것을 보여줍니다 .

귀하의 경우 평가되는 표현식은 다음과 같습니다.

n++,k=3

답변2

내부에서는 $((...))큰따옴표를 사용하는 것처럼 먼저 확장이 수행된 다음 ¹ 결과가 평가됩니다.

따라서 n=3; k=10; echo $((n++,k=$n))(또는 n=1; echo "$((++n + $n))"에 국한되지 않음 ,)에서 평가되는 산술 표현식은 입니다 n++, k=3.

여기에는 다음이 필요합니다.

n=3; k=10; echo "$((n++,k=n))"

(또한 산술 확장은 POSIX 셸의 다른 형태의 단어 확장과 마찬가지로 분할+글로브의 영향을 받기 때문에 따옴표에 유의하세요.)


¹, 일부 쉘은 예를 들어 포함할 $((hash[$key]++))때 올바르게 처리하려고 시도하므로 배열 및 연관 배열이 호출되는 몇 가지 변형을 찾을 수 있습니다.$key]

관련 정보