
Я нашел похожий вопросздесь, но он, похоже, не идентичен, и ни один из ответов не дает нужного мне результата. У меня есть массив, для которого я хочу узнать, сколько элементов он содержит, обращаясь к нему с помощью динамически сгенерированного имени.
declare -a array0=(2 4 2 5) # contains 4 values
indx=0
Name="array$indx" # create a name reference => array0
# I know how to obtain an indexed value by INDIRECT reference:
val0=${!Name[0]}
# I also know how to get array length using DIRECT name
len=${#array0[@]}
Мне нужно найти количество элементовмассив0ссылаясь на него с помощью переменнойИмя
len=${#!Name[@]} # the syntax is incorrect
Есть ли какие-нибудь предложения по реализации?
РЕДАКТИРОВАТЬ:
Я ошибался, когда говорил, что можно получить доступ к записям массива с помощью этого:
val0=${!Name[0]}
Он работает только для indx=0, поэтому, если я захочу получить другие записи из массива, он просто вернет пустую строку:
val4=${!Name[4]} #does not work
или
i=4
val4=${!Name[$i]} # does not work
решение1
С bash-4.3
или выше вы можете использовать namerefs:
a0=(a b c)
i=0
typeset -n Name="a$i"
echo "${#Name[@]}"
или вы всегда можетеиспользоватьeval
. В любом случае, не обманывайтесь, думая, что использование bash
namerefs являетсябезопаснеечем eval
. Как и для eval
, вам все равно нужно убедиться, что содержимое $Name
является допустимым именем переменной оболочки. Значения типа x[`evil-command>&2`0]
все равно приведут к тому, что evil-command
будет выполнено при расширении $Name
или ${#Name}
. То же самое относится к ${!var}
.
Вместо этого ksh93
можно использовать многомерные массивы:
a[0]=(a b c)
i=0
echo "${#a[i][@]}"
zsh
имеет более последовательные способы объединения своих операторов расширения:
a0=(a b c)
i=0
name=a$i
echo ${(P)#name}
( P
для косвенного расширения параметров).
решение2
Вы можете использовать его eval
явно, но не злоупотребляйте:
eval "len=\${#$Name[@]}"