2016-07-05 1 views
2

En utilisant Bash's arrays, je peux stocker une liste dans une variable de tableau et itérer sur les éléments tout en gardant les chaînes entre guillemets contenant des espaces ou des caractères spéciaux ainsi:Comment puis-je stocker une liste de chaînes entre guillemets dans une variable dans Bourne shell? (Sans tableaux Bash)

LIST=(--foo --bar --baz "test 1 2 3") 
for item in "${LIST[@]}"; do 
    echo "$item" 
done 

sortie est:

--foo 
--bar 
--baz 
test 1 2 3 

J'ai un script qui utilise cette fonctionnalité et malheureusement besoin de le porter pour utiliser les cendres de Busybox (qui ne supporte pas les tableaux). J'essaie de trouver un bon moyen de stocker une liste dans laquelle certains éléments peuvent contenir des espaces, tout en conservant le bon nombre d'éléments de la liste.

Cela ne fonctionne pas, par exemple (divise incorrectement test 1 2 3 en éléments séparés):

LIST='--foo --bar --baz "test 1 2 3"' 
for item in $LIST; do 
    echo "$item" 
done 

sortie est:

--foo 
--bar 
--baz 
"test 
1 
2 
3" 

Un idea I found on the Busybox mailing list est d'utiliser set -- pour remplacer les paramètres de position:

set -- --foo --bar --baz "test 1 2 3" 
for item in "[email protected]"; do 
    echo "$item" 
done 

La sortie est co rrect:

--foo 
--bar 
--baz 
test 1 2 3 

Cependant, cette construction aplatit la liste des arguments de position ([email protected]), qui ce script aussi utilisations.

Y a-t-il un moyen raisonnable que je puisse avoir mon gâteau et le manger aussi, et simuler plusieurs tableaux arbitraires dans la variante non-Bash sh?

Répondre

1

La raison pour laquelle la plupart des coquilles fournissent des tableaux d'une certaine sorte est parce que vous ne pouvez pas les simuler en toute sécurité en utilisant plat cordes. Si vous pouvez isoler le code qui a besoin d'un tableau du reste de votre script, vous pouvez l'exécuter dans un sous-shell afin que les paramètres de position puissent être restaurés après la sortie du sous-shell.

(# Nothing in here can rely on the "real" positional 
    # parameters, unless you can fsave them to a fixed set of indiviual 
    # parameters first. 
    first_arg=$1 # etc 
    set -- --foo --bar --baz "test 1 2 3" 
    for item in "[email protected]"; do 
     echo "$item" 
    done 
    # Any other parameters you set or update will likewise revert 
    # to their former values now. 
) 
2

Vous pouvez déclarer une variable \n en elle:

list='--foo\n--bar\n--baz\n"test 1 2 3"' 

# then iterate it using 
echo -e "$list" | while read -r line; do echo "line=[$line]"; done 

Sortie:

line=[--foo] 
line=[--bar] 
line=[--baz] 
line=["test 1 2 3"]