Je vais seulement donner quelques conseils généraux dans cette réponse, et non des repères. Les repères sont le seul moyen de répondre de manière fiable aux questions sur les performances. Mais comme vous ne dites pas la quantité de données que vous manipulez et la fréquence à laquelle vous effectuez cette opération, il n'y a aucun moyen de faire un benchmark utile. Ce qui est plus efficace pour 10 éléments et ce qui est plus efficace pour 1000000 éléments n'est souvent pas le même.
En règle générale, invoquer des commandes externes coûte plus cher que de faire quelque chose avec des constructions de shell pur, tant que le code de shell pur n'implique pas de boucle. D'un autre côté, une boucle shell qui itère sur une grande chaîne ou une grande quantité de chaîne est susceptible d'être plus lente qu'une invocation d'un outil spécial. Par exemple, votre appel de boucle cut
pourrait être sensiblement lent dans la pratique, mais si vous trouvez un moyen de faire le tout avec une seule cut
invocation, cela sera probablement plus rapide que de faire la même chose avec la manipulation de chaînes dans le shell.
Notez que le point de coupure peut varier considérablement d'un système à l'autre. Cela peut dépendre du noyau, de la configuration de l'ordonnanceur du noyau, du système de fichiers contenant les exécutables externes, de la quantité de pression CPU vs mémoire actuellement, et de nombreux autres facteurs.
N'appelez pas expr
pour effectuer de l'arithmétique si vous êtes préoccupé par la performance. En fait, n'appelez pas du tout expr
pour effectuer de l'arithmétique. Les shells ont une arithmétique intégrée, qui est plus claire et plus rapide que l'invocation expr
.
Vous semblez utiliser bash, puisque vous utilisez des constructions bash qui n'existent pas dans sh. Alors pourquoi diable n'utilisez-vous pas un tableau? Un tableau est la solution la plus naturelle, et il est probable qu'elle soit aussi la plus rapide. Notez que les indices de tableau commencent à 0.
list=(1 2 3 5 9 8 6 90 84 9 3 2 15 75 55)
for ((count = 0; count += 3; count < ${#list[@]})); do
echo "${list[$count]}"
done
Votre script pourrait bien être plus rapide si vous utilisez sh, si votre système a dash ou ksh sh
plutôt que bash. Si vous utilisez sh, vous n'obtenez pas de tableaux nommés, mais vous obtenez tout de même un tableau de paramètres positionnels, que vous pouvez définir avec set
. Pour accéder à un élément à une position qui n'est pas connue avant l'exécution, vous devez utiliser eval
(prenez soin de citer les choses correctement!).
# List elements must not contain whitespace or ?*\[
list='1 2 3 5 9 8 6 90 84 9 3 2 15 75 55'
set $list
count=1
while [ $count -le $# ]; do
eval "value=\${$count}"
echo "$value"
count=$((count+1))
done
Si vous ne souhaitez accéder au tableau qu'une seule fois et que vous allez de gauche à droite (en sautant certaines valeurs), vous pouvez utiliser à la shift
place des indices de variable.
# List elements must not contain whitespace or ?*\[
list='1 2 3 5 9 8 6 90 84 9 3 2 15 75 55'
set $list
while [ $# -ge 1 ]; do
echo "$1"
shift && shift && shift
done
L'approche la plus rapide dépend du shell et du nombre d'éléments.
Une autre possibilité consiste à utiliser le traitement de chaîne. Il a l'avantage de ne pas utiliser les paramètres de position, vous pouvez donc les utiliser pour autre chose. Ce sera plus lent pour de grandes quantités de données, mais il est peu probable que cela fasse une différence notable pour de petites quantités de données.
# List elements must be separated by a single space (not arbitrary whitespace)
list='1 2 3 5 9 8 6 90 84 9 3 2 15 75 55'
while [ -n "$list" ]; do
echo "${list% *}"
case "$list" in *\ *\ *\ *) :;; *) break;; esac
list="${list#* * * }"
done