comment décaler la valeur du tableau dans bash


8

nous voulons construire 6 dossiers de points de montage comme exemple

/data/sdb
/data/sdc
/data/sdd
/data/sde
/data/sdf
/data/sdg

nous avons donc écrit ce simple script bash en utilisant un tableau

folder_mount_point_list="sdb sdc sdd sde sdf sdg"

folderArray=( $folder_mount_point_list )

counter=0
for i in disk1 disk2 disk3 disk4 disk4 disk5 disk6
do
folder_name=${folderArray[counter]}
mkdir /data/$folder_name
let counter=$counter+1
done

maintenant nous voulons changer le code sans compteur et laisser = $ counter = counter + 1

est-il possible de décaler chaque boucle du tableau afin d'obtenir la prochaine valeur du tableau?

comme quelque chose comme

${folderArray[++]}

1
à quoi for i in disk1 disk2 disk3 disk4 disk4 disk5 disk6ça sert car il n'est pas utilisé dans le corps de la boucle?
RomanPerekhrest

1
... et quel est l'intérêt d'utiliser un compteur? Pourquoi ne courez-vous pas simplement for i in "your_list_goes_here"; do mkdir /data/"$i"; done?
don_crissti

Réponses:


10

Une remarque générale. Il n'est pas logique de définir un tableau comme celui-ci:

folder_mount_point_list="sdb sdc sdd sde sdf sdg"
folderArray=( $folder_mount_point_list )

Vous feriez cela à la place:

folderArray=(sdb sdc sdd sde sdf sdg)

Passons maintenant à votre question:

set -- sdb sdc sdd sde sdf sdg
for folder_name; do
    mkdir "/data/$folder_name"
done

ou

set -- sdb sdc sdd sde sdf sdg
while [ $# -gt 0 ]; do
    mkdir "/data/$1"
    shift
done

pouvons-nous faire l'ensemble pour la variable comme ensemble - $ list_of_folders (tandis que list_of_folders = "sdb sdc sdd sde"
yael

@yael Oui, vous pouvez utiliser set -- $list_of_foldersmais encore une fois: les variables de chaîne ne sont pas la voie à suivre:set -- "${folders[@]}"
Hauke ​​Laging

1
pourquoi utilisez-vous même set -- ....? ce hack n'est nécessaire que dans les shells qui ne prennent pas en charge les tableaux - il n'est pas nécessaire de le faire dans un shell qui prend en charge les tableaux. for folder_name in "${folderArray[@]}"; do ... ; donec'est tout ce qu'il faut.
cas

juste une question, est-il possible de faire quelque chose comme - $ {folderArray [++]}
yael

@cas c'est ce que j'ai dans ma réponse. Je ne comprends pas non plus cette setapproche.
PesaLe

14

Pour répondre à la question dans le titre, vous pouvez "décaler" un tableau avec la notation sous-chaîne / sous-matrice. ( shiftlui - même ne fonctionne qu'avec les paramètres de position.)

$ a=(a b c d e)
$ a=("${a[@]:1}")
$ echo "${a[@]}"
b c d e

De même, pour «faire sauter» le dernier élément du tableau: a=("${a[@]:0:${#a[@]} - 1}" )ouunset "a[${#a[@]}-1]"

Donc, si vous le souhaitez, vous pouvez le faire:

a=(foo bar doo)
b=(123 456 789)
while [ "${#a[@]}" -gt 0 ] ; do
    echo "$a $b"
    a=("${a[@]:1}")
    b=("${b[@]:1}")
done

Mais il supprime les tableaux, donc juste l'indexation comme d'habitude pourrait être mieux. Ou utilisez plutôt un tableau associatif:

declare -A arr=([foo]=123 [bar]=456 [doo]=789)

4

Vous pouvez simplement parcourir toutes les valeurs, sans décalage nécessaire:

folderArray=(sdb sdc sdd sde sdf sdg)

for folder in "${folderArray[@]}"; do
    mkdir "/data/$folder"
done

3

Vous n'avez pas besoin de boucle pour ça:

folderArray=(sdb sdc sdd sde sdf sdg)
IFS=,
eval mkdir /data/{"${folderArray[*]}"}

L'astuce est que si un tableau est entre guillemets doubles avec indice *( "${array[*]}"), il se développe en un seul mot avec la valeur de chaque élément du tableau séparé par le premier caractère de la IFSvariable. Après cela, nous utilisons un mécanisme d'expansion d'accolade pour attacher /data/à chaque membre du tableau et evalévaluer le tout.


Pourquoi si compliqué? cd /data ; mkdir "${folderArray[@]}"J'ai fait la même chose auparavant mais je ne le ferais pas dans un cas comme celui-ci. Mais +1 pour l'approche avancée.
Hauke ​​Laging

@HaukeLaging Oui, ce serait plus simple en cas de mkdircommande. Et même un tableau n'est pas nécessaire, cd /data; mkdir abc defcomme le ferait une personne normale. Mais ne peut pas être aussi simple pour d'autres tâches, il est donc bon de savoir comment attacher rapidement une chaîne à chaque élément du tableau sans boucle.
jimmij

juste une question, est-il possible de faire quelque chose comme - $ {folderArray [++]}
yael

1
@yael Vous pouvez faire quelque chose comme echo "${folderArray[((counter++))]}"si vous aimez vraiment cette approche. Les choses à l'intérieur (())sont évaluées comme des mathématiques (notez l'absence de $devant counter).
jimmij

1
et quand vous commencez à écrire du code shell comme ça, vous vous rendez compte que mettre un peu de temps à apprendre perl ou python serait une bonne idée. c'est-à-dire juste parce que vous pouvez faire quelque chose avec bash, ne signifie pas que vous devriez le faire .
cas
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.