come spostare il valore dell'array in bash


8

vogliamo costruire 6 cartelle di mount point come esempio

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

così abbiamo scritto questo semplice script bash usando array

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

ora vogliamo cambiare il codice senza contatore e lasciare = $ counter = counter + 1

è possibile spostare ciascun loop dell'array per ottenere il valore dell'array successivo?

come qualcosa del genere

${folderArray[++]}

1
a cosa for i in disk1 disk2 disk3 disk4 disk4 disk5 disk6serve perché non viene utilizzato all'interno del corpo del loop?
RomanPerekhrest,

1
... e che senso ha usare un contatore? Perché non corri semplicemente for i in "your_list_goes_here"; do mkdir /data/"$i"; done?
don_crissti,

Risposte:


7

Un'osservazione generale. Non ha senso definire un array come questo:

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

Dovresti fare questo invece:

folderArray=(sdb sdc sdd sde sdf sdg)

Ora alla tua domanda:

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

o

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

possiamo fare il set per la variabile come set - $ list_of_folders (mentre list_of_folders = "sdb sdc sdd sde"
yael

@yael Sì, puoi usarlo di set -- $list_of_foldersnuovo: le variabili String non sono la strada da percorrere:set -- "${folders[@]}"
Hauke ​​Laging

1
perché stai persino usando set -- ....? quell'hacking è necessario solo nelle shell che non supportano le matrici - non è necessario in una shell che supporta le matrici. for folder_name in "${folderArray[@]}"; do ... ; doneè tutto ciò che serve.
Cas

solo una domanda, c'è qualche scelta per fare qualcosa del tipo - $ {folderArray [++]}
yael

@cas è quello che ho nella mia risposta. Non capisco neanche questo setapproccio.
Pesa

11

Per rispondere alla domanda nel titolo, è possibile "spostare" un array con la notazione substring / subarray. ( shiftfunziona da solo con i parametri posizionali.)

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

Allo stesso modo, per "estrarre" l'ultimo elemento dall'array: a=("${a[@]:0:${#a[@]} - 1}" )ounset "a[${#a[@]}-1]"

Quindi, se lo volessi, potresti farlo:

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

Ma elimina gli array, quindi solo l'indicizzazione come al solito potrebbe essere migliore. O forse usa invece un array associativo:

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

3

Non è necessario alcun loop per questo:

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

Il trucco è che se una matrice è racchiusa tra virgolette doppie con subscript *( "${array[*]}") si espande in una singola parola con il valore di ciascun elemento della matrice separato dal primo carattere della IFSvariabile. Dopodiché utilizziamo il meccanismo di espansione della parentesi graffa per collegarci /data/a ciascun membro dell'array e evalutilizzare l'intera operazione.


Perché così complicato? cd /data ; mkdir "${folderArray[@]}"Ho fatto lo stesso prima, ma in un caso del genere non lo farei. Ma +1 per l'approccio avanzato.
Hauke ​​Laging,

@HaukeLaging Sì, sarebbe più semplice in caso di mkdircomando. E anche l'array non è necessario, proprio cd /data; mkdir abc defcome farebbe una persona normale. Ma non potrebbe essere così semplice per altre attività, quindi è bene sapere come collegare rapidamente una stringa a ciascun elemento dell'array senza un ciclo.
jimmij,

solo una domanda, c'è qualche scelta per fare qualcosa del tipo - $ {folderArray [++]}
yael

1
@yael Puoi fare qualcosa del genere echo "${folderArray[((counter++))]}"se ti piace davvero questo approccio. La roba all'interno (())è valutata come matematica (notare la mancanza di $davanti counter).
jimmij,

e quando inizi a scrivere codice shell in questo modo, ti rendi conto che dedicare un po 'di tempo all'apprendimento di perl o python sarebbe una buona idea. cioè solo perché puoi fare qualcosa con bash, non significa che dovresti .
Cas

3

Puoi semplicemente passare in rassegna tutti i valori, senza spostare:

folderArray=(sdb sdc sdd sde sdf sdg)

for folder in "${folderArray[@]}"; do
    mkdir "/data/$folder"
done
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.