web-dev-qa-db-fra.com

Convertir une chaîne de texte dans bash en tableau

Comment puis-je convertir une chaîne comme celle-ci dans BASH à un tableau en bash!

J'ai une chaîne str qui contient "title1 title2 title3 title4 title5" (Titres séparés par une espace)

Je veux que la str soit modifiée en un tableau qui stockera chaque titre dans chaque index. 

11
Ayush Mishra

Pour convertir la chaîne en tableau, dites:

$ str="title1 title2 title3 title4 title5"
$ arr=( $str )

Le shell effectuerait le fractionnement de Word sur les espaces sauf si vous citez la chaîne.

Pour boucler sur les éléments du tableau ainsi créé:

$ for i in "${arr[@]}"; do echo $i; done
title1
title2
title3
title4
title5
26
devnull

Une autre méthode utilisant read:

read -a array <<< $str
1
perreal

Je suis malheureusement dans une position où j'ai un script Shell de longue date qui passe de l'utilisation interne de variables scalaires à l'utilisation de tableaux. Mais , les utilisateurs sont également autorisés à définir ces variables eux-mêmes, éventuellement, avec un fichier créé au démarrage.

Alors , je devais trouver un moyen de convertir de manière conditionnelle un scalaire en tableau, selon que le script source de l'utilisateur était déclaré de la nouvelle manière ou à l'ancienne.

Ma solution est exagérée pour le cas simple ci-dessus, mais je voulais la documenter pour les autres personnes à la recherche de cette solution, car il était facile de trouver quelque chose qui traitait mon cas d'utilisation.

La seule façon pour moi de gérer de manière fiable toutes les options en toute sécurité est donc:

convert_array() {
        __array_name="$1"; shift
        __declaration="$(declare -p "$__array_name" 2>/dev/null)"
        if [ -z "${__declaration}" ]; then
                # variable is not set
                eval "${__array_name}=()"
        Elif [ "$(echo "${__declaration}" | grep -c '^declare \-a')" -eq 0 ]; then
                # variable is not an array
                __existing_value="$(eval echo "\${$__array_name}" | sed -e 's,^[[:space:]]*,,' -e 's,[[:space:]]*$,,')"
                unset "${__array_name?}"
                IFS=" " read -r -a "${__array_name?}" <<< "${__existing_value}"
        fi
}

Il gère proprement tous les cas: variable existante, tableau existant et pas défini du tout.

Notez également que cela peut sembler excessif:

__existing_value="$(eval echo "\${$__array_name}" | sed -e 's,^[[:space:]]*,,' -e 's,[[:space:]]*$,,')"

... il gère le cas où la plupart des gens construisent leurs configurations d'origine, par exemple:

ADDITIONAL_OPTIONS="${ADDITIONAL_OPTIONS} -Xmx2g"
ADDITIONAL_OPTIONS="${ADDITIONAL_OPTIONS} -Dsome.property=foo"

Dans ces cas, la variable $ADDITIONAL_OPTIONS commencera par un espace. Si vous savez que vos entrées n'auront pas besoin d'être ajustées, ce bit est inutile.

test_foo() {
        convert_array FOO
        for VAR in "${FOO[@]}"; do
                echo "var=$VAR"
        done
}

$ FOO="foo bar baz"
$ test_foo
var=foo
var=bar
var=baz
$ unset FOO
$ test_foo
$ FOO=(foo bar baz "something with spaces")
$ test_foo
var=foo
var=bar
var=baz
var=something with spaces
0
Benjamin Reed