Sorunun kısa açıklaması:
Orada yerleşik mı bash yönteminin dizinin adı (yani bir değişkende saklanır) dinamiktir bash dizi öğe sayısını saymak için, olmadan tam dizinin kopya yapmadan veya kullanarak başvurmadan eval
?
Daha fazla bilgi:
Bash parametresi ikamesini kullanarak aşağıdakileri yapabilirsiniz:
- Bir dizinin uzunluğunun belirlenmesi:
myArr=(A B C); echo ${#myArr[@]}
. - Bir değişkeni ada göre dolaylı olarak referanslayın:
NAME=myVar; echo ${!NAME}
(bu, dizi öğeleri için de geçerlidir):
NAME=myArr[1]; echo ${!NAME}
Ancak bir dizinin adı başka bir değişkende saklanıyorsa, dizideki öğelerin sayısı nasıl belirlenebilir? (Bu , yukarıdaki iki parametre ikamesinin bir kombinasyonu olarak düşünülebilir .) Örneğin:
myArr=(A B C D)
NAME=myArr
# Get the number of elements in the array indirectly referenced by NAME.
count=${#$NAME[@]} # This syntax is invalid. What is the right way?
Aşağıda BAŞARISIZ tüm birden fazla deneme vardır:
# Setup for following attempts:
myArr=(A B C D)
NAME=myArr
EXPR1=$NAME[@] # i.e. EXPR1='myArr[@]'
EXPR2=#$NAME[@] # i.e. EXPR2='#myArr[@]'
# Failed attempts to get the lengh of the array indirectly:
1. count=${#$NAME[@]} # ERROR: bash: ...: bad substitution
2. count=${#!EXPR1} # ERROR: bash: !EXPR}: event not found
3. count=${#\!EXPR1} # ERROR: bash: ...: bad substitution
4. count=${!#EXPR1} # ERROR: bash: ...: bad substitution
5. count=${!EXPR2} # Returns NULL
Ayrıca yukarıdaki diğer bazı varyantları denedim, ama henüz ya da olmadan çalışan bir şey bulamadım: (A) dizinin bir kopyasını yapmak veya (B) kullanarak eval
.
Çalışma yöntemleri:
Bunu çözmenin muhtemelen optimal olmayan birkaç yolu vardır (ama yanılıyorsam beni düzeltin):
Yöntem 1: diziyi kopyalama
Diziyi başka bir (statik olarak adlandırılmış) değişkene atayın ve içindeki öğelerin sayısını alın.
EXPR=$NAME[@]
arrCopy=( "${!EXPR}" )
count=${#arrCopy}
Yöntem 2: Kullanım eval
EXPR="count=\${#$NAME[@]}" # i.e. 'count=${myArr[@]}'
eval $EXPR
# Now count is set to the length of the array
Özet:
Bir dizinin uzunluğunu dolaylı olarak belirlemek için bash'de yerleşik bir yöntem (yani parametre ikame sözdizimi) var mı? Değilse, bunu yapmanın en etkili yolu nedir? eval
Yukarıdaki yöntem olduğunu varsayıyorum , ancak güvenlik veya performans sorunları var eval
mı?
time bash -c 'a=(1 a +); c=a; for ((i=0;i<100000;i++)); do eval "echo \${#$c[@]}"; done' > /dev/null
ve benzer şekilde e=$c[@]; d=("${!e}); echo ${#d[@]}
döngüde. Değerlendirme kopyalanarak geçirilen sürenin yaklaşık% 90'ını aldı. Ve sanırım boşluk sadece dizi ve elemanları büyür.