Bref énoncé de la question:
Existe-t-il une méthode bash intégrée pour compter le nombre d'éléments dans le tableau bash, où le nom du tableau est dynamique (c'est-à-dire stocké dans une variable), sans recourir à une copie complète du tableau ou à l'utilisation eval
?
Plus d'information:
En utilisant la substitution de paramètres bash, on peut faire ce qui suit:
- Déterminer la longueur d'un tableau:
myArr=(A B C); echo ${#myArr[@]}
. - Référencez indirectement une variable par son nom:
NAME=myVar; echo ${!NAME}
(cela s'applique également aux éléments du tableau):
NAME=myArr[1]; echo ${!NAME}
Mais si le nom d'un tableau est stocké dans une autre variable, comment déterminer le nombre d'éléments dans le tableau? (On pourrait considérer cela comme une combinaison des deux substitutions de paramètres ci-dessus.) Par exemple:
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?
Vous trouverez ci-dessous plusieurs tentatives qui ont toutes échoué:
# 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
J'ai également essayé d'autres variantes de ce qui précède, mais je n'ai encore rien trouvé qui fonctionne sans: (A) faire une copie du tableau ou (B) en utilisant eval
.
Les méthodes de travail:
Il existe deux façons de résoudre ce problème qui ne sont probablement pas optimales (mais corrigez-moi si je me trompe):
Méthode 1: copiez le tableau
Attribuez le tableau à une autre variable (nommée statiquement) et obtenez le nombre d'éléments qu'elle contient.
EXPR=$NAME[@]
arrCopy=( "${!EXPR}" )
count=${#arrCopy}
Méthode 2: utiliser eval
EXPR="count=\${#$NAME[@]}" # i.e. 'count=${myArr[@]}'
eval $EXPR
# Now count is set to the length of the array
Résumé:
Existe-t-il une méthode intégrée (c'est-à-dire une syntaxe de substitution de paramètres) dans bash pour déterminer indirectement la longueur d'un tableau? Sinon, quelle est la manière la plus efficace de procéder? Je suppose que c'est la eval
méthode ci-dessus, mais y a-t-il des problèmes de sécurité ou de performances avec eval
?
time bash -c 'a=(1 a +); c=a; for ((i=0;i<100000;i++)); do eval "echo \${#$c[@]}"; done' > /dev/null
:, et de même avec e=$c[@]; d=("${!e}); echo ${#d[@]}
dans la boucle. L'évaluation a pris environ 90% du temps nécessaire à la copie. Et je suppose que l'écart ne fera qu'augmenter plus le tableau et ses éléments seront grands.