wie man den Array-Wert in Bash verschiebt

8

Wir möchten als Beispiel 6 Mount-Point-Ordner erstellen

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

Also haben wir dieses einfache Bash-Skript mit Array geschrieben

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

Jetzt wollen wir den Code ohne Zähler ändern und = $ counter = counter + 1 lassen

Ist es möglich, jede Schleife des Arrays zu verschieben, um den nächsten Array-Wert zu erhalten?

als so etwas wie

${folderArray[++]}
Yael
quelle
1
Wofür wird for i in disk1 disk2 disk3 disk4 disk4 disk5 disk6es nicht im Loop-Body verwendet?
RomanPerekhrest
1
... und was bringt es, einen Zähler zu benutzen? Warum rennst du nicht einfach for i in "your_list_goes_here"; do mkdir /data/"$i"; done?
don_crissti

Antworten:

10

Eine allgemeine Bemerkung. Es ist nicht sinnvoll, ein Array wie folgt zu definieren:

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

Sie würden dies stattdessen tun:

folderArray=(sdb sdc sdd sde sdf sdg)

Nun zu Ihrer Frage:

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

oder

set -- sdb sdc sdd sde sdf sdg
while [ $# -gt 0 ]; do
    mkdir "/data/$1"
    shift
done
Hauke ​​Laging
quelle
können wir die Menge für Variable als Menge machen - $ list_of_folders (während list_of_folders = "sdb sdc sdd sde"
yael
@yael Ja, Sie können set -- $list_of_foldersaber noch einmal verwenden: String-Variablen sind nicht der set -- "${folders[@]}"
richtige
1
warum sind Sie selbst set -- ....? Dieser Hack wird nur in Shells benötigt, die keine Arrays unterstützen. In einer Shell, die Arrays unterstützt, ist er nicht erforderlich. for folder_name in "${folderArray[@]}"; do ... ; doneist alles was benötigt wird.
Cas
Nur eine Frage, gibt es eine Wahl, um etwas wie - $ {folderArray [++]}
Yael
@cas das habe ich in meiner Antwort. Ich verstehe diesen setAnsatz auch nicht.
PesaDer
14

Um die Frage im Titel zu beantworten, können Sie ein Array mit der Teilzeichenfolge / Subarray-Notation "verschieben". ( shiftselbst funktioniert nur mit den Positionsparametern.)

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

Ebenso, um das letzte Element aus dem Array zu entfernen: a=("${a[@]:0:${#a[@]} - 1}" )oderunset "a[${#a[@]}-1]"

Wenn Sie möchten, können Sie Folgendes tun:

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

Die Arrays werden jedoch verworfen, sodass eine bessere Indizierung möglicherweise besser ist. Oder verwenden Sie stattdessen ein assoziatives Array:

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

Sie können einfach alle Werte durchlaufen, ohne dass eine Verschiebung erforderlich ist:

folderArray=(sdb sdc sdd sde sdf sdg)

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

Dafür brauchen Sie keine Schleife:

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

Der Trick besteht darin, dass ein Array mit doppelten Anführungszeichen mit subscript *( "${array[*]}") zu einem einzelnen Wort erweitert wird, wobei der Wert jedes Array-Elements durch das erste Zeichen der IFSVariablen getrennt ist. Danach verwenden wir den Klammererweiterungsmechanismus , um /data/an jedem Array-Mitglied eine Verbindung evalherzustellen und das Ganze zu bearbeiten.

jimmij
quelle
Warum so kompliziert? cd /data ; mkdir "${folderArray[@]}"Ich habe das gleiche schon einmal gemacht, würde es aber in einem solchen Fall nicht tun. Aber +1 für den fortgeschrittenen Ansatz.
Hauke ​​Laging
@HaukeLaging Ja, das wäre im Falle eines mkdirBefehls einfacher . Und selbst ein Array wird nicht benötigt, so cd /data; mkdir abc defwie es ein normaler Mensch tun würde. Könnte aber für andere Aufgaben nicht so einfach sein, daher ist es gut zu wissen, wie man schnell eine Zeichenfolge ohne Schleife an jedes Array-Element anfügt.
Jimmyij
Nur eine Frage, gibt es eine Wahl, um etwas wie - $ {folderArray [++]}
Yael
1
@yael Du kannst so etwas machen, echo "${folderArray[((counter++))]}"wenn dir dieser Ansatz wirklich gefällt. Sachen im Inneren (())werden als Mathe bewertet (beachten Sie das Fehlen von $vor counter).
Jimmy
1
und wenn Sie anfangen, Shell-Code so zu schreiben, erkennen Sie, dass es eine gute Idee wäre, ein wenig Zeit in das Erlernen von Perl oder Python zu investieren. dh , nur weil man kann etwas mit bash tun, bedeutet nicht , Sie sollten .
Cas