명령 줄에서 로컬 Bourne과 같은 쉘에서 어레이 지원을 간결하게 테스트하는 방법이 있습니까?
이것은 항상 가능합니다 :
$ arr=(0 1 2 3);if [ "${arr[2]}" != 2 ];then echo "No array support";fi
또는 $SHELL쉘 버전 테스트 및 테스트 :
$ eval $(echo "$SHELL --version") | grep version
그런 다음 액세스 권한이 있다고 가정하고 매뉴얼 페이지를 읽습니다. (심지어 거기에서 편지를 쓰고 /bin/bash, 나는 가정하고 모든 본쉘 긴 옵션을 인정 --version, KSH에 대한 그 휴식 예를 들어 .)
스크립트 시작시 또는 호출 전에 사용 섹션에 무인으로 통합 할 수있는 간단한 테스트를 찾고 있습니다.
답변
당신은 본쉘 (다른 많은 조개 등을 제한 할 가정 csh, tcsh, rc, es또는 fish지원 배열하지만 껍질 같은 Bourne 씨에 동시에 호환 스크립트를 작성하고 완전히 다른 및 통역과 마찬가지로 사람들은 까다 롭고 일반적으로 무의미 호환되지 않는 언어), 구현 간에는 상당한 차이가 있습니다.
배열을 지원하는 Bourne과 같은 쉘은 다음과 같습니다.
- 
ksh88(배열을 구현하는 최초의 하나가, ksh88 여전히 같은 발견ksh은 또한의 기초가 어디 대부분 기존의 상용 유닉스에서sh)- 배열은 1 차원입니다
 - 배열로 정의되어 있습니다 
set -A array foo bar또는set -A array -- "$var" ...당신은 보장 할 수없는 경우 그$var이 시작되지 않습니다-또는+. - 배열 인덱스는에서 시작 
0합니다. - 개별 배열 요소는로 지정됩니다 
a[1]=value. - 배열이 드물다. 즉 
a[5]=foo경우에도 작동a[0,1,2,3,4]설정되지 않은 및 해제를 떠날 것이다. ${a[5]}indice 5의 요소에 액세스하기 위해 (배열이 드문 경우 반드시 여섯 번째 요소는 아닙니다). 는5산술 표현식이있을 수있다.- 배열 크기와 아래 첨자는 4096으로 제한됩니다.
 ${#a[@]}배열에서 할당 된 요소의 수입니다 (가장 큰 할당 된 지표는 아님).- 지정된 첨자 목록을 알 수있는 방법은 없습니다 (4096 개 요소를 개별적으로 테스트하는 것 제외 
[[ -n "${a[i]+set}" ]]). $a와 동일합니다${a[0]}. 즉, 배열은 스칼라 변수에 추가 값을 제공하여 확장합니다.
 - 
pdksh그리고 파생 상품 (이것은ksh때로는sh여러 BSD 의 기초이며 ksh93 소스가 해제되기 전에 유일한 오픈 소스 ksh 구현이었습니다) :주로 좋아
ksh88하지만 참고하십시오 :- 일부 오래된 구현은을 지원하지 않았습니다 
set -A array -- foo bar(--필요하지 않았습니다). ${#a[@]}가장 큰 배정 된 지표의 지수에 1을 더한 것입니다. (a[1000]=1; echo "${#a[@]}"배열에 요소가 하나만 있어도 1001을 출력합니다.- 최신 버전에서는 배열 크기가 더 이상 제한되지 않습니다 (정수 크기 제외).
 - 최근 버전 
mksh에서 영감을 몇 가지 추가 연산자를 가지고bash,ksh93또는zsh라 과제처럼a=(x y),a+=(z),${!a[@]}할당 된 인덱스의 목록을 얻을 수 있습니다. 
 - 일부 오래된 구현은을 지원하지 않았습니다 
 - 
zsh.zsh배열은 일반적으로 더 나은 디자인과 최고의 가지고 있습니다ksh및csh배열을. 그것들은 비슷ksh하지만 큰 차이점이 있습니다.- 인덱스는 0이 아닌 1에서 시작합니다 ( 
ksh에뮬레이션 제외 ). Bourne 배열 (zsh$ argv 배열로 표시 되는 위치 매개 변수 $ @ ) 및csh배열 과 일치 합니다. - 그것들은 정규 / 스칼라 변수와는 별개의 유형입니다. 운영자는 일반적으로 기대하는 것처럼 다르게 적용됩니다. 
$a는 같지${a[0]}않지만 배열의 비어 있지 않은 요소로 확장됩니다 ("${a[@]}"에서와 같은 모든 요소에 대해ksh). - 그것들은 희소 배열이 아닌 일반 배열입니다. 
a[5]=1작동하지만 1에서 4까지의 모든 요소가 할당되지 않은 경우 빈 문자열을 할당합니다. 따라서${#a[@]}(${#a}ksh에서 indice 0의 요소 크기 와 동일 )는 배열의 요소 수 와 가장 큰 할당 된 indice입니다. - 연관 배열이 지원됩니다.
 - 배열로 작업하기위한 수많은 연산자가 지원되며 여기에 나열하기에는 너무 큽니다.
 - 로 정의 된 배열 
a=(x y).set -A a x y또한 작동하지만set -A a -- x yksh 에뮬레이션이 아닌 경우 지원되지 않습니다 (--zsh 에뮬레이션에는 필요하지 않음). 
 - 인덱스는 0이 아닌 1에서 시작합니다 ( 
 - 
ksh93. (여기서는 최신 버전을 설명합니다). FOSS로 출시 된 지금은ksh93오랫동안 실험으로 간주 된 실험 이 점점 더 많은 시스템에서 발견 될 수 있습니다. 예를 들어,/bin/sh(Bourne 쉘을 대체/usr/xpg4/bin/sh한 POSIX 쉘은 여전히을 기반으로합니다ksh88) 및ksh의Solaris 11입니다. 그 배열은 ksh88을 확장하고 향상시킵니다.a=(x y)는 배열을 정의하는 데 사용될 수 있지만a=(...)복합 변수 (a=(foo=bar bar=baz)) 를 정의하는 데에도 사용 되므로a=()모호하며 배열이 아닌 복합 변수를 선언합니다.- 배열은 다차원 ( 
a=((0 1) (0 2)))이며 배열 요소는 복합 변수 (a=((a b) (c=d d=f)); echo "${a[1].c}") 일 수도 있습니다 . a=([2]=foo [5]=bar)구문은 한 번에 스파 스 배열을 정의 할 수 있습니다.- 크기 제한이 해제되었습니다.
 - 의 범위는 
zsh아니지만 배열을 조작하는 데 지원되는 많은 연산자가 있습니다. "${!a[@]}"배열 인덱스 목록을 검색합니다.- 연관 배열도 별도의 유형으로 지원됩니다.
 
 - 
bash.bashGNU 프로젝트의 쉘입니다. 그것은으로 사용되는shOS / X 및 일부 GNU / Linux 배포판의 최신 버전에.bash배열은 주로 및의ksh88일부 기능이있는 배열을 에뮬레이션 합니다 .ksh93zsha=(x y)지원됩니다. 지원set -A a x y되지 않습니다 .a=()빈 배열을 만듭니다 (에 복합 변수 없음bash)."${!a[@]}"지수 목록.a=([foo]=bar)ksh93및 에서 제공되는 구문뿐만 아니라 다른 구문도 지원합니다zsh.- 최신 
bash버전은 또한 연관 배열을 별도의 유형으로 지원합니다. 
 - 
yash. 비교적 최신의 깨끗한 멀티 바이트 인식 POSIX sh 구현입니다. 널리 사용되지 않습니다. 배열은 다음과 비슷한 또 다른 깨끗한 API입니다.zsh- 배열이 희박하지 않습니다
 - 배열 인덱스는 1에서 시작
 - 로 정의 및 선언 
a=(var value) array내장으로 삽입, 삭제 또는 수정 된 요소array -s a 5 value해당 요소가 사전에 지정되지 않은 경우 5 번째 요소 를 수정하면 실패합니다.- 배열의 요소 수는 
${a[#]},${#a[@]}리스트와 요소의 크기 인. - 배열은 별도의 유형입니다. 
a=("$a")요소를 추가하거나 수정하기 전에 스칼라 변수를 배열로 재정의 해야 합니다. - 로 호출되면 배열이 지원되지 않습니다 
sh. 
 
따라서 배열 지원을 감지하는 것을 볼 수 있습니다.
if (unset a; set -A a a; eval "a=(a b)"; eval '[ -n "${a[1]}" ]'
   ) > /dev/null 2>&1
then
  array_supported=true
else
  array_supported=false
fi
그 배열을 사용할 수있을만큼 충분하지 않습니다. 배열을 전체 및 개별 요소로 할당하기 위해 래퍼 명령을 정의하고 희소 배열을 만들지 않도록해야합니다.
처럼
unset a
array_elements() { eval "REPLY=\"\${#$1[@]}\""; }
if (set -A a -- a) 2> /dev/null; then
  set -A a -- a b
  case ${a[0]}${a[1]} in
    --) set_array() { eval "shift; set -A $1"' "$@"'; }
        set_array_element() { eval "$1[1+(\$2)]=\$3"; }
        first_indice=0;;
     a) set_array() { eval "shift; set -A $1"' -- "$@"'; }
        set_array_element() { eval "$1[1+(\$2)]=\$3"; }
        first_indice=1;;
   --a) set_array() { eval "shift; set -A $1"' "$@"'; }
        set_array_element() { eval "$1[\$2]=\$3"; }
        first_indice=0;;
    ab) set_array() { eval "shift; set -A $1"' -- "$@"'; }
        set_array_element() { eval "$1[\$2]=\$3"; }
        first_indice=0;;
  esac
elif (eval 'a[5]=x') 2> /dev/null; then
  set_array() { eval "shift; $1=("'"$@")'; }
  set_array_element() { eval "$1[\$2]=\$3"; }
  first_indice=0
elif (eval 'a=(x) && array -s a 1 y && [ "${a[1]}" = y ]') 2> /dev/null; then
  set_array() { eval "shift; $1=("'"$@")'; }
  set_array_element() {
    eval "
      $1=(\${$1+\"\${$1[@]}"'"})
      while [ "$(($2))" -ge  "${'"$1"'[#]}" ]; do
        array -i "$1" "$2" ""
      done'
    array -s -- "$1" "$((1+$2))" "$3"
   }
  array_elements() { eval "REPLY=\${$1[#]}"; }
  first_indice=1
else
  echo >&2 "Array not supported"
fi
그리고 당신은 배열을 가진 요소에 액세스 "${a[$first_indice+n]}"하여, 전체 목록 "${a[@]}"과 래퍼 함수를 사용 ( array_elements, set_array, set_array_element) (에서 배열의 요소 수를 얻기 위해 $REPLY), 전체 또는 할당 개별 요소로 배열을 설정합니다.
노력할만한 가치가 없을 것입니다. perlBourne / POSIX 셸 배열을 사용 하거나 제한합니다 "$@".
내부적으로 배열을 사용하는 함수를 정의하기 위해 사용자의 대화식 쉘에서 일부 파일을 소싱하려는 의도가 있다면 유용한 몇 가지 참고 사항이 있습니다.
로컬 범위 (함수 또는 익명 함수)의 배열 zsh과 유사하게 배열을 구성 할 수 있습니다 ksh.
myfunction() {
  [ -z "$ZSH_VERSION" ] || setopt localoption ksharrays
  # use arrays of indice 0 in this function
}
또한 다음을 사용하여 에뮬레이션 할 수 있습니다 ksh( ksh배열 및 기타 여러 영역과의 호환성 향상 ).
myfunction() {
  [ -z "$ZSH_VERSION" ] || emulate -L ksh
  # ksh code more likely to work here
}
이를 염두에두고 파생 버전의 이전 버전과 이전 버전에 대한 지원을 기꺼이 포기 yash하고 희소 배열을 만들지 않는 한 일관성있게 사용할 수 있어야합니다.ksh88pdksh
a[0]=fooa=(foo bar)(하지만 아닙니다a=())"${a[#]}","${a[@]}","${a[0]}"
이 이러한 기능에 emulate -L ksh그동안, zsh사용자가 정상적으로 그 / 그녀의 배열 zsh을 방법을 사용하여.
답변
eval배열 구문을 시도하는 데 사용할 수 있습니다 .
is_array_support() (
  eval 'a=(1)'
) >/dev/null 2>&1
if is_array_support; then
  echo support
else
  echo not
fi