Bash의 배열 이름에 변수가 있는 배열에 값을 추가하는 방법은 무엇입니까?

Bash의 배열 이름에 변수가 있는 배열에 값을 추가하는 방법은 무엇입니까?

내 스크립트에 그룹 이름 목록이 포함된 배열이 있습니다. 이 목록에는 고정된 수의 요소가 없습니다.

GROUPS=(group1 group2 group3)

이 그룹 집합의 각 요소에는 알 수 없는 수의 값이 있을 수 있습니다. 이름에 변수가 포함된 배열 세트를 동적으로 생성합니다. 여기서 VARIABLE은 그룹 이름입니다.

for VARIABLE in "${GROUPS[@]}"
do
  declare -a ARRAY_${VARIABLE}
done

일련의 값을 반복하고 조건이 충족되면 해당 값이 속한 배열에 새 요소로 추가하고 싶습니다.

for (( VALUES=1; VALUES<=10; VALUES++ ));
do 
  if the VALUE belongs to GROUPx assign it to the array for GROUPx 
    ARRAY_$VARIABLE+=("$VALUES")
  fi
done

이는 그룹에 속하는 값을 포함하는 배열로 끝나야 합니다. 즉:

ARRAY_group1= 1 2 5 9 10
ARRAY_group2= 3 7 
ARRAY_group3= 4 6 8

하지만 예상치 못한 토큰 "$VALUES" 근처에서 bash: 구문 오류가 계속 발생합니다. ARRAY라는 배열에 할당하면 완벽하게 작동하지만 동적으로 생성해야 하는 알 수 없는 개수의 배열에 스크립트의 값을 할당해야 합니다.

이름에 연결된 변수가 포함된 문자열에 값을 추가한 다음 sed를 사용하여 개별 값을 선택할 수 있지만 해당 표현식에 대한 올바른 구문도 찾을 수 없습니다.

let TEST_$VARIABLE="$TEST_$VARIABLE:$VALUES"
let TEST_$VARIABLE="${TEST_$VARIABLE}:$VALUES"
let TEST_$VARIABLE="$((TEST_$VARIABLE)):$VALUES"
let TEST_$VARIABLE="$((TEST_$VARIABLE))" ":$VALUES"

몇 가지 다른 방법을 시도했지만 모두 똑같은 문제가 있었습니다. bash는 실제로 이름에 변수를 사용하는 것을 좋아하지 않지만 동적으로 생성해야 하므로 이름에 변수를 포함해야 합니다.

몇 가지 다른 방법을 시도했지만 모든 구문 오류와 잘못된 대체 오류를 피할 수 있도록 bash에서 이름에 변수가 포함된 변수를 안정적으로 참조하는 방법을 알고 계시다면 정말 감사하겠습니다.

Tldr: bash가 ARRAY[@]를 처리하는 것과 같은 방식으로 bash가 ARRAY_$VARIABLE[@]을 처리할 수 있게 하는 몇 가지 구문이 있습니까?

답변1

이름 참조

나는 nameref가 당신이 원하는 것이라고 생각합니다.

name=foo
declare -a array_$name
declare -n target=array_$name
for x in asdf 'white space' ; do target+=("$x"); done 
declare -p array_$name

산출:

declare -a array_foo=([0]="asdf" [1]="white space")

평가하다, 선언하다, 하자

또 다른 더 나쁜 방법은 이러한 값을 사용 eval하거나 설정하는 것입니다.declare

eval$인용이 까다로워지므로 실수로 값의 s를 확장하고 싶지는 않을 것입니다 .

eval "array_$name+=(\"\$x\")"

declare배열에 추가하는 것을 구현하기가 약간 어렵습니다. 할당하려는 인덱스를 알고 있다면 매우 간단합니다.

declare "array_$name[$i]=$x"

(요소 수를 얻으려면 array_$namenameref 또는 다시 필요한 것 같습니다 eval.)

당신은 여기와 let약간 비슷하다고 언급했지만 declare산술 표현식의 경우 일반적인 경우에는 적합하지 않습니다.

name=a; 
let "test_$name=12+34"        # sets test_a to 46
let "test_$name=foo"          # reads the _value_ of variable foo!
let "test_$name=foo bar"      # this is an error.

대체 데이터 구조

또는 각 값이 하나만 있을 수 있는 경우 데이터 구조를 뒤집어 각 값의 그룹 ID를 단일 배열에 저장합니다.

for (( val=1; val <= 10; val++ )); do
     groupid=$(find_groupid "$val")
     variables[$val]=$groupid
done

그런 다음 전체 배열을 반복하고 관심 없는 그룹을 무시합니다.

또는 값에 공백이 포함되어 있지 않으면 문자열을 내부 배열로 사용하세요. 반복하려면 다음과 같이 하십시오.

for group in "${groups[@]}"; do 
    for item in $group; do       # no quotes here, we want wordsplitting
        ...

(또는 연관 배열을 사용하여 그룹 이름을 저장합니다.)

관련 정보