ZSH에서 배열 첨자로 나타날 수있는 산술 표현식은 무엇입니까?

Dec 22 2020

ZSH 매뉴얼 ( zshparam(1))은 다음과 같습니다.

Array Subscripts
       Individual elements of an array may be selected using a subscript.  A
       subscript of the form `[exp]' selects the single element exp, where
       exp is an arithmetic expression which will be subject to arithmetic
       expansion as if it were surrounded by `$((...))'.

그러나 이것은 빠르게 실패합니다.

mc% arr=(a b c d e)     
mc% echo $arr[$#arr] e mc% echo $arr[$(($#arr))]
e
mc% echo $arr[$(($#arr - 1))] d mc% echo $arr[$#arr - 1]  
zsh: invalid subscript

질문 : 왜 그리고 예외는 무엇입니까?

참고 : 이 질문은 don_crissti의 대답 에서 비롯된 것으로 $arr[RANDOM % $#arr + 1], 무작위 요소에 액세스 할 것을 제안 하지만 위의 오류가 발생합니다.

답변

5 Gilles'SO-stopbeingevil' Dec 23 2020 at 03:45

기술적으로 모든 표현식은 아래 첨자로 나타날 수 있습니다. 문제는 파서가 원하는 것을 아래 첨자에 넣는 것입니다. 공백을 포함한 일부 문자는 절대 만들지 않습니다. 아래 첨자가 단어의 일부이기 때문에 단어 구성 문자 만 아래 첨자의 일부가 될 수 있습니다.

mc% echo $arr[ 1] zsh: invalid subscript mc% echo $arr[1 ]
zsh: invalid subscript
mc% echo $arr[$#arr - 1]
zsh: invalid subscript
mc% echo $arr[$#arr-1]
d

아래 첨자 파서는 첫 번째 유효하지 않은 문자에서 중지되고 zsh가 종료 닫는 괄호를 확인하기 전에 "유효하지 않은 아래 첨자"오류가 트리거됩니다.

mc% echo $arr[ 1  
zsh: invalid subscript

에서 echo $arr[ 1]: 공간 이후의 부분은 사실 별개의 단어로 간주됩니다 echo의 확장으로 인한 두 개의 인수를 받게 $arr[하고 1]그 zsh을 인해 구문 분석 실패에 어떤 명령을 실행하기 시작되지 않습니다 제외. 산술 표현식의 일부로 생각할 수있는 내용이 실제로 그렇게 구문 분석되지 않는다는 것을 알 수있는 몇 가지 경우가 있습니다. 예를 들면 다음과 같습니다.

mc% echo $arr[1<<2]   
heredoc> << is a heredoc operator, not part of the subscript.
heredoc> 2]
zsh: invalid subscript

물론 단어로 구성되지 않은 문자는 산술 표현식이나 명령 대체와 같은 중첩 확장의 일부로 몰래 들어갈 수 있습니다.

mc% echo $arr[$[1&3]] 
a
mc% echo $arr[`echo "1 + 2"`]  
c

매개 변수 확장이 큰 따옴표로 묶인 경우 모든 문자 (균형 닫는 대괄호 또는 끝 따옴표 제외)는 아래 첨자의 일부가됩니다. 큰 따옴표 안에있는 모든 문자는 사실상 단어 구성 문자이기 때문입니다. 마찬가지로 매개 변수 확장에서 중괄호를 사용하는 경우 zsh는 아래 첨자에 대한 }닫는 대괄호 ]를 찾기 전에 매개 변수 확장에 대한 닫는 중괄호 를 찾습니다. 따라서 단어로 구성되지 않는 문자는이를 아래 첨자로 만듭니다.

mc% echo "$arr[$#arr - 1]" d mc% echo ${arr[$#arr - 1]}
d

핵심 세부 사항에 대해 자세히 알아 보려면 관련 함수가 parse_subscript에서 호출됩니다 getindex.