Dans un script Bash, je voudrais diviser une ligne en morceaux et les stocker dans un tableau.
La ligne :
Paris, France, Europe
Je voudrais les avoir dans un tableau comme celui-ci :
array[0] = Paris
array[1] = France
array[2] = Europe
Je voudrais utiliser un code simple, la vitesse de la commande n'a pas d'importance. Comment puis-je faire ?
IFS=', ' read -r -a array <<< "$string"
Notez que les caractères de $IFS
sont traités individuellement comme des séparateurs, de sorte que dans ce cas, les champs peuvent être séparés par soit une virgule ou un espace plutôt que par la séquence des deux caractères. Il est intéressant de noter que les champs vides ne sont pas créés lorsque la virgule ou l'espace apparaît dans l'entrée car l'espace est traité de manière spéciale.
Pour accéder à un élément individuel :
echo "${array[0]}"
Pour itérer sur les éléments :
for element in "${array[@]}"
do
echo "$element"
done
Pour obtenir à la fois l'indice et la valeur :
for index in "${!array[@]}"
do
echo "$index ${array[index]}"
done
Le dernier exemple est utile car les tableaux de Bash sont épars. En d'autres termes, vous pouvez supprimer un élément ou en ajouter un et les indices ne sont pas contigus.
unset "array[1]"
array[42]=Earth
Pour obtenir le nombre d'éléments dans un tableau :
echo "${#array[@]}"
Comme mentionné ci-dessus, les tableaux peuvent être clairsemés et vous ne devriez pas utiliser la longueur pour obtenir le dernier élément. Voici comment procéder à partir de la version 4.2 de Bash :
echo "${array[-1]}"
dans n'importe quelle version de Bash (à partir de la 2.05b) :
echo "${array[@]: -1:1}"
Les décalages négatifs plus grands sélectionnent plus loin de la fin du tableau. Notez l'espace avant le signe moins dans l'ancienne forme. Il est nécessaire.
Voici une façon de procéder sans paramétrer l'IFS :
string="1:2:3:4:5"
set -f # avoid globbing (expansion of *).
array=(${string//:/ })
for i in "${!array[@]}"
do
echo "$i=>${array[i]}"
done
L'idée est d'utiliser le remplacement de chaînes de caractères :
${string//substring/replacement}
pour remplacer toutes les correspondances de $substring par des espaces blancs, puis utiliser la chaîne substituée pour initialiser un tableau :
(element1 element2 ... elementN)
Remarque : cette réponse utilise l'opérateur [split+glob] (https://unix.stackexchange.com/q/108963/79743). Ainsi, pour éviter l'expansion de certains caractères (tels que *
), il est bon de mettre en pause le globbing pour ce script.
Il m’arrive parfois que la méthode décrite dans la réponse acceptée ne fonctionne pas, surtout si le séparateur est un retour chariot.
Dans ces cas-là, j'ai résolu le problème de la manière suivante :
string='first line
second line
third line'
oldIFS="$IFS"
IFS='
'
IFS=${IFS:0:1} # this is useful to format your code with tabs
lines=( $string )
IFS="$oldIFS"
for line in "${lines[@]}"
do
echo "--> $line"
done