Bash: 배열에 대한 간접 참조에 액세스

Bash: 배열에 대한 간접 참조에 액세스

내 스크립트에는 "versions_" 문자열로 시작하는 다양한 변형 변수가 있습니다. 예를 들면 다음과 같습니다.

versions_a=("1" "2")
versions_b=("3" "4")

다음 변수를 반복하여 기본 배열에 액세스하고 싶습니다.

#!/usr/bin/env bash
versions_a=("1" "2")
versions_b=("3" "4")


for i in ${!versions_*}; do
    
    #Ideally if statement here if underlying array is empty, continue to next iteration

    echo "${i} contains ${i[*]}"
    versions=(${!i})
    echo "versions has ${versions[@]}"
   
    for x in "${versions[@]}"; do 
      echo ${x} #should print 1, then 2, then 3, then 4
    done
done

예상 출력:

versions_a has 1 2
versions has 1 2
1
2
versions_b has 3 4
versions has 3 4
3
4

현재 출력:

versions_a contains versions_a
versions has 1
1
versions_b contains versions_b
versions has 3
3

답변1

가장 쉬운 방법은 여기에서 nameref를 사용하는 것입니다(bash 4.3 이상 가정).

#! /bin/bash -

versions_a=( 1 2 )
versions_b=( 3 4 )
versions_c=( -n '*' )

for varname in "${!versions_@}"; do
  typeset -n versions="$varname"

  IFS=,
  printf '%s\n' "$varname contains ${versions[*]}"

  for x in "${versions[@]}"; do
    printf '%s\n' "$x"
  done
done

이것은 만든다:

versions_a contains 1,2
1
2
versions_b contains 3,4
3
4
versions_c contains -n,*
-n
*

또한 매개변수 확장은 따옴표로 묶어야 하며 echo임의의 데이터를 출력하는 데 사용할 수 없다는 점을 기억하세요. 및 "$*"또는 의 확장은 의 "${array[*]}"현재 값에 따라 달라집니다 $IFS(여기서는 로 설정하여 설명함 ,).

답변2

바라보다이 답변:

[@]까다로운 점은 간접적으로 전달하려는 변수에 배열 요소(또는 모든 요소)를 포함 해야 한다는 것입니다 .

...또는 [*]그것이 당신이 원하는 것이라면. 이 같은:

#!/usr/bin/env bash
versions_a=("1" "2")
versions_b=("3" "4")
versions_c=()


for i in ${!versions_*}; do
    
    group=${i#*"_"} #removes the 'versions_'
    versions="${i}[@]"
    last_version=${!versions: -1}

    if [[ -z ${last_version} ]]; then
        echo "Empty, skipping."
        continue
    fi

    echo "${i} as ${group} has ${!versions}"
   
    for x in "${!versions}"; do 
      echo "${group} & ${x}"
    done
done

산출

versions_a as a has 1 2
a & 1
a & 2
versions_b as b has 3 4
b & 3
b & 4
Empty, skipping.

관련 정보