하위 문자열을 기준으로 연관 배열을 반복합니다.

하위 문자열을 기준으로 연관 배열을 반복합니다.

아래 코드에서는 루프에 몇 가지 연관 배열을 만듭니다. 이는 문자열 식별자와 연도라는 두 개의 문자열로 구성됩니다. 일단 생성되면 식별자만을 기반으로 루프에서 배열에 액세스하고 싶습니다.

#!/bin/bash

# Declare associative arrays of journal-year combinations
A_JOURNAL_LIST={JF,JFE,RFS}
B_JOURNAL_LIST={JBF,JFI,JMCB}
ALL_JOURNAL_LIST={JF,JFE,RFS,JBF,JFI,JMCB}
for year in {1998..2000} {2009..2011}
do
  eval "A_$year=($A_JOURNAL_LIST-$year) ;"
  eval "B_$year=($B_JOURNAL_LIST-$year) ;"
  eval "all_$year=($ALL_JOURNAL_LIST-$year) ;"
done  

A_1999JF-1999 JFE-1999 RFS-1999여기에서는 예를 들어 다음과 같이 확장되는 여러 배열을 쉽게 얻을 수 있습니다 .

for journal in A B all
do
  echo "${'$journal'_1999[@]}"
done

기대했다

JF-1999 JFE-1999 RFS-1999
JBF-1999 JFI-1999 JMCB-1999
JF-1999 JFE-1999 RFS-1999 JBF-1999 JFI-1999 JMCB-1999

나는 bad substitution error항상 하나를 얻고 많은 조합을 시도합니다. 뭐가 문제 야?

답변1

에 오신 것을 환영합니다eval 지옥! 한번 사용하기 시작하면 절대로 제거할 수 없습니다.

for journal in A B all
do
  eval "echo \"\${${journal}_1999[@]}\""
done

이 작업을 수행하는 더 좋은 방법이 있을 수 있지만 쉘 스크립트에서 연관 배열이나 다른 중첩 배열을 사용하는 것을 결코 귀찮게 하지 않습니다. 이러한 데이터 구조가 필요한 경우 기본적으로 이를 지원하는 스크립팅 언어를 사용하는 것이 더 나을 수 있습니다.

실제로 bash는 연관 배열을 어느 정도 지원합니다. 그들이 당신을 위해 작동하는지 여부는 또 다른 질문입니다. 어쨌든 다른 쉘로 이식 가능하지 않습니다.

답변2

가변 간접여기에 도움이 될 것입니다:

for journal in A B all
do
    indirect="${journal}_1999[@]"
    echo "$journal: ${!indirect}"
done

산출

A: JF-1999 JFE-1999 RFS-1999
B: JBF-1999 JFI-1999 JMCB-1999
all: JF-1999 JFE-1999 RFS-1999 JBF-1999 JFI-1999 JMCB-1999

평가를 다시 작성할 필요가 없습니다. 배열의 배열은 bash가 기본적으로 제공하는 것이 아니므로 공백으로 구분된 문자열과 임시 저장소를 사용해야 합니다.

# Declare associative arrays of journal-year combinations
a_journal_list=( {JF,JFE,RFS} )
b_journal_list=( {JBF,JFI,JMCB} )
all_journal_list=( "${a_journal_list[@]}" "${b_journal_list[@]}" )
declare -a a b all

for year in {1998..2000} {2009..2011}
do
    # store year-specific values as space-separated strings
    a[$year]=$( printf "%s-$year " "${a_journal_list[@]}" )
    b[$year]=$( printf "%s-$year " "${b_journal_list[@]}" )
    all[$year]=$( printf "%s-$year " "${all_journal_list[@]}" )
done  

selected_years=( 1998 1999 2000 )
for journal in a b all
do
    # I'll use the positional params for temp storage of the accumulated array
    set --
    for year in "${selected_years[@]}"
    do
        indirect="${journal}[$year]"
        # variable is unquoted to allow word splitting
        set -- "$@" ${!indirect}
    done
    echo $journal
    printf "%s\n" "$@"
done

답변3

Bash의 배열에 대해 몇 가지 오해가 있다고 생각합니다.

정렬

   Bash provides one-dimensional indexed and associative array variables.  Any variable may be used as  an
   indexed  array; the declare builtin will explicitly declare an array.  There is no maximum limit on the
   size of an array, nor any requirement that members be indexed or assigned contiguously.  Indexed arrays
   are  referenced  using  integers  (including  arithmetic  expressions)  and are zero-based; associative
   arrays are referenced using arbitrary strings.  Unless otherwise noted, indexed array indices  must  be
   non-negative integers.

   An  indexed  array  is  created automatically if any variable is assigned to using the syntax name[sub‐
   script]=value.  The subscript is treated as an arithmetic expression that must evaluate  to  a  number.
   To  explicitly  declare  an  indexed  array,  use  declare  -a name (see SHELL BUILTIN COMMANDS below).
   declare -a name[subscript] is also accepted; the subscript is ignored.

   Associative arrays are created using declare -A name.

   Attributes may be specified for an array variable  using  the  declare  and  readonly  builtins.   Each
   attribute applies to all members of an array.

   Arrays  are  assigned  to  using  compound assignments of the form name=(value1 ... valuen), where each
   value is of the form [subscript]=string.  Indexed array assignments do not require anything but string.
   When  assigning  to  indexed arrays, if the optional brackets and subscript are supplied, that index is
   assigned to; otherwise the index of the element assigned is the last index assigned to by the statement
   plus one.  Indexing starts at zero.

   When assigning to an associative array, the subscript is required.

   This  syntax  is  also  accepted  by the declare builtin.  Individual array elements may be assigned to
   using the name[subscript]=value syntax introduced above.  When assigning to an indexed array,  if  name
   is  subscripted  by  a  negative number, that number is interpreted as relative to one greater than the
   maximum index of name, so negative indices count back from the end of the array, and  an  index  of  -1
   references the last element.

관련 정보