Подтвердить что ты не робот

Массив массивов в bash

Я пытаюсь прочитать строку ввода строки за строкой, которая содержит поля, разделенные периодами. Я хочу поместить их в массив массивов, чтобы потом перебирать их. Ввод выглядит нормально, но "нажатие" на массив (inData) не работает.

Код идет:

Input file: 
GSDB.GOSALESDW_DIST_INVENTORY_FACT.MONTH_KEY
GSDB.GOSALESDW_DIST_INVENTORY_FACT.ORGANIZATION_KEY


infile=${1}

OIFS=$IFS
IFS=":"

cat ${infile} | while read line
do
      line=${line//\./:}
      inarray=(${line})
#      echo ${inarray[@]}
#      echo ${#inarray[@]}      
#      echo ${inarray[0]}
#      echo ${inarray[1]}
#      echo ${inarray[2]}

      inData=("${inData[@]}" "${inarray[@]}")
done 
IFS=$OIFS

echo ${#inData[@]}   

for ((i = 0; i < ${#inData[@]}; i++))
do
 echo $i
    for ((j = 0; j < ${#inData[$i][@]}; j++))
    do
       echo ${inData[$i][$j]}
    done
done
4b9b3361

Ответ 2

Поле гнезда поля в bash, но оно не может обойти этот пример.

declare -a pages

pages[0]='domain.de;de;https'
pages[1]='domain.fr;fr;http'

for i in "${pages[@]}"
do
        arr=(${i//;/ })
        site=${arr[0]}
        language=${arr[1]}
        protocol=${arr[2]}
done

Ответ 3

Зная, что вы можете разделить строку на "массив". Вы можете создать список списков. Например, список баз данных на серверах БД.

dbServersList=('db001:app001,app002,app003' 'db002:app004,app005' 'dbcentral:central')

# Loop over DB servers
for someDbServer in ${dbServersList[@]}
do
    # delete previous array/list (this is crucial!)
    unset dbNamesList
    # split sub-list if available
    if [[ $someDbServer == *":"* ]]
    then
        # split server name from sub-list
        tmpServerArray=(${someDbServer//:/ })
        someDbServer=${tmpServerArray[0]}
        dbNamesList=${tmpServerArray[1]}
        # make array from simple string
        dbNamesList=(${dbNamesList//,/ })
    fi

    # Info
    echo -e "\n----\n$someDbServer\n--"

    # Loop over databases
    for someDB in ${dbNamesList[@]}
    do
        echo $someDB
    done
done

Результат выше:

----
db001
--
app001
app002
app003

----
db002
--
app004
app005

----
dbcentral
--
central

Ответ 4

Я боролся с этим, но нашел неудобный компромисс. В общем случае, столкнувшись с проблемой, решение которой связано с использованием структур данных в Bash, вы должны переключиться на другой язык, например Python. Игнорируя этот совет и двигаясь прямо:

Мои варианты использования обычно включают списки списков (или массивы массивов) и перебирают их. Обычно вы не хотите гнездиться гораздо глубже, чем это. Кроме того, большинство массивов представляют собой строки, которые могут содержать или не содержать пробелы, но обычно не содержат специальных символов. Это позволяет мне использовать несовместимый синтаксис для выражения внешнего массива, а затем использовать обычную обработку bash для строк, чтобы получить второй список или массив. Вам нужно будет обратить внимание на ваш IFS-разделитель, obvi.

Таким образом, ассоциативные массивы могут дать мне способ создать список списков, например:

declare -A JOB_LIST=(
   [job1] = "a set of arguments"
   [job2] = "another different list"
   ...
)

Это позволяет вам перебирать оба массива, например:

for job in "${!JOB_LIST[@]}"; do
  /bin/jobrun ${job[@]}
done

Ah, за исключением того, что вывод списка ключей (с помощью магического ${!...}) означает, что вы не будете перемещать ваш список по порядку. Поэтому еще один необходимый хак - сортировать порядок ключей, если это важно для вас. Порядок сортировки зависит от вас; Мне удобно пользоваться буквенно-цифровой сортировкой, и прибегать к aajob1 bbjob3 ccjob6 вполне приемлемо.

Поэтому

declare -A JOB_LIST=(
   [aajob1] = "a set of arguments"
   [bbjob2] = "another different list"
   ...
)
sorted=($(printf '%s\n' "${!JOB_LIST[@]}"| /bin/sort))
for job in "${sorted[@]}"; do
   for args in "${job[@]}"; do
     echo "Do something with ${arg} in ${job}"
   done
done

Ответ 5

Вы можете использовать (de) ссылки на массивы, как в этом script:

#!/bin/bash

OFS=$IFS     # store field separator
IFS="${2: }" # define field separator
file=$1      # input file name

unset a      # reference to line array
unset i j    # index
unset m n    # dimension

### input

i=0
while read line
do
  a=A$i
  unset $a
  declare -a $a='($line)'
  i=$((i+1))
done < $file
# store number of lines
m=$i

### output

for ((i=0; i < $m; i++))
do
  a=A$i
  # get line size
  # double escape '\\' for sub shell '``' and 'echo'
  n=`eval echo \\${#$a[@]}`
  for (( j = 0; j < $n; j++))
  do
    # get field value
    f=`eval echo \\${$a[$j]}`
    # do something
    echo "line $((i+1)) field $((j+1)) = '$f'"
  done
done

IFS=$OFS

Кредит https://unix.stackexchange.com/info/199348/dynamically-create-array-in-bash-with-variables-as-array-name