Bash 매개변수 확장

Bash 매개변수 확장

Bash(내 경우에는 4+)에서는 문자열에서 사용할 수 있는 모든 인수 확장 함수를 배열에서 사용할 수 있다는 것을 읽거나 들었습니다. 오늘은 배열 팝핑(array popping)과 비슷한 기능을 설정해보려고 했습니다. 다음 구문과 비슷한 것을 사용했습니다.

declare -a arr=( 0 1 2 3 4 5 )
arr=( ${arr[@]:0:(-1)} )

놀랍게도 Bash는 다음과 같이 불평했습니다.

-bash: (-1): substring expression < 0

문자열을 사용하여 이 작업을 수행하면 구문이 예상대로 작동합니다. 예를 들어:

var="see spot run"
var="${var:0:(-1)}"
echo "$var"
  see spot ru

나는 배열에 대해 이것을 할 수 있다는 것을 알고 있습니다(그리고 그것이 작동하는지 테스트했습니다):

declare -a arr=( 0 1 2 3 4 5 )
arr=( ${arr[@]:0:((${#arr[@]}-1))} )
echo ${arr[@]}
    0 1 2 3 4

문제는 모든 문자열 인수 확장이 배열에서 작동하는 경우 (-1) 구문이 예상대로 작동하지 않는 이유는 무엇입니까? 내가 여기서 단순한 것을 간과하고 있는 걸까요, 아니면 더 깊은 뭔가가 있는 걸까요?

답변1

이 질문에 대한 대답은 모든 문자열 매개변수 확장이 배열에서 작동하는 것은 아니라는 것 같습니다. 주석을 보고 Bash 참조 매뉴얼(don_crissti에서 제공한 링크, 감사합니다)을 읽은 후 하위 문자열 확장에 대한 음수 인덱싱에 대한 경고가 표시됩니다. Bash 매뉴얼에 명시된 바와 같이 (쉘 매개변수 확장):

${parameter:offset:length}

이를 하위 문자열 확장이라고 합니다. 그것은 확장된다길이지정된 문자에서 시작하는 매개변수 값의 문자오프셋. 인수가 @인덱스 배열이거나 연관 배열 이름인 경우 아래 설명과 같이 결과가 다릅니다.@*

...

@인수가 또는 첨자가 붙은 인덱스 배열 이름인 경우 *결과는 다음과 같습니다.길이로 시작하는 배열 멤버입니다 ${parameter[offset]}. 음수오프셋지정된 배열의 최대 인덱스보다 1 큰 값을 기준으로 합니다.다음과 같은 경우 확장 오류가 발생합니다.길이0보다 작은 숫자로 평가됩니다.

don_crissti가 지적했듯이 여기서 수행되는 길이 평가는 참조 문자열/하위 문자열의 길이가 아니라 길이 속성을 할당하는 동안 수행되는 평가입니다. don_crissti의 예는 다음과 같습니다.

a=2
printf %s\\n "${arr[@]:3:(a+1)}"

길이 할당(a+1)의 산술 평가 부분이 음수 값을 산출하거나 내 경우와 같이 값 자체가 정적으로 음수로 전달되는 경우 이는 확장 오류입니다. 즉, 다음 두 상황 모두 확장 오류가 발생할 수 있습니다.

declare -a arr=( 0 1 2 3 4 5 )
# length evaluates to (-1)
a=2
printf %s\\n "${arr[@]:3:(a-3)}"
  -bash: (a-3): substring expression < 0

# or length is assigned as (-1)
arr=( ${arr[@]:0:(-1)} )
  -bash: (-1): substring expression < 0

Bash 매뉴얼에 따르면 이는 두 경우 모두에서 예상되는 동작입니다.

관련 정보