Kurze Erklärung der Frage:
Gibt es eine integrierte Bash-Methode, um die Anzahl der Elemente im Bash-Array zu zählen, wobei der Name des Arrays dynamisch ist (dh in einer Variablen gespeichert ist), ohne eine vollständige Kopie des Arrays zu erstellen oder zu verwenden eval
?
Mehr Informationen:
Mit der Bash-Parametersubstitution können Sie Folgendes tun:
- Bestimmen Sie die Länge eines Arrays :
myArr=(A B C); echo ${#myArr[@]}
. - Indirekt auf eine Variable mit Namen verweisen:
NAME=myVar; echo ${!NAME}
(Dies gilt auch für Array-Elemente):
NAME=myArr[1]; echo ${!NAME}
Aber wenn der Name eines Arrays in einer anderen Variablen gespeichert ist, wie kann man die Anzahl der Elemente im Array bestimmen? (Man könnte dies als eine Kombination der beiden oben genannten Parametersubstitutionen betrachten.) Zum Beispiel:
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?
Unten sind mehrere Versuche, die alle fehlschlagen:
# 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
Ich habe auch einige andere Varianten der oben genannten ausprobiert, aber noch nichts gefunden, was ohne Folgendes funktioniert: (A) Erstellen einer Kopie des Arrays oder (B) Verwenden von eval
.
Arbeitsmethoden:
Es gibt einige Möglichkeiten, dies zu lösen, die wahrscheinlich nicht optimal sind (aber korrigieren Sie mich, wenn ich falsch liege):
Methode 1: Kopieren Sie das Array
Weisen Sie das Array einer anderen (statisch benannten) Variablen zu und ermitteln Sie die Anzahl der darin enthaltenen Elemente.
EXPR=$NAME[@]
arrCopy=( "${!EXPR}" )
count=${#arrCopy}
Methode 2: Verwenden eval
EXPR="count=\${#$NAME[@]}" # i.e. 'count=${myArr[@]}'
eval $EXPR
# Now count is set to the length of the array
Zusammenfassung:
Gibt es eine integrierte Methode (dh Parametersubstitutionssyntax) in bash, um die Länge eines Arrays indirekt zu bestimmen? Wenn nicht, wie geht das am effizientesten? Ich nehme an, es ist die eval
oben beschriebene Methode, aber gibt es Sicherheits- oder Leistungsprobleme mit eval
?
time bash -c 'a=(1 a +); c=a; for ((i=0;i<100000;i++)); do eval "echo \${#$c[@]}"; done' > /dev/null
und ähnlich mit e=$c[@]; d=("${!e}); echo ${#d[@]}
in der Schleife. Die Auswertung dauerte etwa 90% der Zeit, die für das Kopieren benötigt wurde. Und ich nehme an, dass die Lücke nur größer wird, je größer das Array und seine Elemente sind.