Comment porter sur des tableaux de style bash sur ash?

12

Il y a quelque temps, j'ai écrit un script bash qui devrait maintenant pouvoir fonctionner dans l'environnement avec ash.

Dans bashc'était:

services=( "service1.service"
           "service2.service"                                       
           "service3.service" )  

for service in "${services[@]}"
do
   START $service                   
done

START()
{
   echo "Starting "$1
   systemctl start $1
}

En réalité, il existe environ 40 services dans la gamme, et je veux rendre cette transition aussi indolore et propre que possible. J'ai toujours utilisé des bashismes. Maintenant, je suis pressé de rendre les scripts plus portables.

Pour des raisons de portabilité, il serait probablement intéressant d'avoir une ashsolution pure . Mais puisque j'ai un assez robuste busyboxà ma disposition, je pourrais sacrifier une certaine portabilité. Seulement si la lisibilité s'améliore beaucoup, car le script "propre" est aussi une métrique.

Quelle serait la solution portable et propre dans ce cas?

métamorphose
la source

Réponses:

8

Avant que les tableaux soient dans bash, kshet d'autres shells, la méthode habituelle était de choisir un délimiteur qui ne se trouvait dans aucun des éléments (ou un qui était rare pour minimiser tout échappement requis), et itérer sur une chaîne contenant tous les éléments, séparés par ce délimiteur. Les espaces blancs sont généralement le choix de délimiteur le plus pratique car le shell divise déjà les "mots" par les espaces par défaut (vous pouvez définir IFS si vous souhaitez qu'il se divise sur quelque chose de différent).

Par exemple:

# backslash-escape any non-delimiter whitespace and all other characters that
# have special meaning to the shell, e.g. globs, parenthesis, ampersands, etc.
services='service1.service service2.service service3.service'

for s in $services ; do  # NOTE: do not double-quote $services here.
  START "$s"
done

$servicesne doit PAS être entre guillemets ici parce que nous voulons que le shell le divise en "mots".

cas
la source
3

les cendres n'ont pas de tableaux. La seule chose qui se rapproche est les paramètres de position, donc vous pouvez faire

set -- "service1.service" \
       "service2.service" \
       "service3.service"

for service in "$@"
do
   START $service
done
glenn jackman
la source
3

Si vous devez vous référer à la liste des services une seule fois, vous pouvez utiliser un here-doc:

while IFS= read -r service
do
   START "$service"
done << END
service1.service
service2.service
service3.service
END

Notez que les noms de service ne doivent pas être cités dans la liste (bien qu'ils "$service"devraient probablement être cités, sauf si vous avez une bonne raison de ne pas le faire). Si vous souhaitez que les noms de service soient en retrait, utilisez <<-plutôt que <<et indentez les noms avec des onglets:

while IFS= read -r service
do
   START "$service"
done <<- END
        service1.service
        service2.service
        service3.service
END
Scott
la source