Tracks
/
Bash
Bash
/
Lehrplan
/
Mehr über Arrays
Me

Mehr über Arrays in Bash

{one: "1 Übung", other: "%{count} Übungen"}

Über Mehr über Arrays

Arrays haben wir im Kapitel Arrays eingeführt. Dieses Dokument zeigt dir weitere Möglichkeiten, Arrays zu verwenden.

Die Elemente eines Arrays zu einem einzigen String zusammenfügen

Im vorigen Array-Kapitel hast du "${myarray[@]}" mit dem @-Index gesehen, womit das Array in die einzelnen Elemente expandiert wird. Manchmal möchtest du aber alle Elemente zu einem einzigen String zusammenfügen. Dafür verwendest du den *-Index:

echo "${myarray[*]}"

Die Expansion muss in doppelte Anführungszeichen eingeschlossen werden.

Bash verwendet das erste Zeichen der eingebauten Variable IFS als Trennzeichen. Standardmäßig besteht $IFS aus Leerzeichen, Tabulator und Zeilenumbruch.

myarray=(one two three four)
mystring="${myarray[*]}"
declare -p mystring
# => declare -- mystring="one two three four"

Wir können die Variable IFS anpassen, um ein anderes Trennzeichen zu verwenden:

myarray=(one two three four)
IFS=","
mystring="${myarray[*]}"
declare -p mystring
# => declare -- mystring="one,two,three,four"
Advanced
Wir können das in eine Funktion kapseln. Klick für Details.
join() {
    local IFS=$1
    shift
    local elements=("$@")
    echo "${elements[*]}"
}

join ":" "${myarray[@]}"     # note, the "@" index
# => "one:two:three:four"

Wenn wir IFS in der Funktion lokalisieren, müssen wir den alten Wert nicht sichern und im globalen Gültigkeitsbereich nicht wiederherstellen.

Als Verfeinerung: Der spezielle Parameter "$*" hat in Anführungszeichen dieselbe Funktionalität, sodass wir keine Kopie der Argumente der Funktion sichern müssen:

join() {
    local IFS=$1
    shift
    echo "$*"
}
Ohne eine Funktion ist es eine gute Möglichkeit, IFS in einer Subshell zu ändern, um zu vermeiden, dass sie in der aktuellen Shell geändert wird. Klick für Details.
(IFS=","; echo "${myarray[*]}")

Die runden Klammern erzeugen eine Subshell (eine Kopie der aktuellen Shell). Wenn die Befehle in den Klammern fertig sind, beendet sich die Subshell und die geänderte Variable IFS verschwindet.

Beachte, dass das nicht funktioniert: IFS="," echo "${myarray[*]}". Die Parameterexpansion erfolgt zuerst, bevor die Shell die geänderte Variable IFS auf den Befehl echo anwendet.

Array-Ausschnitte

Du hast vielleicht schon die Parameterexpansion "${variable:offset:length}" gesehen, die zu einem Teilstring des Werts der Variable expandiert. Dasselbe können wir mit Arrays machen, um einen Ausschnitt des Arrays zu expandieren.

myarray=(one two three four)

subarray=("${myarray[@]:0:2}")
declare -p subarray
# => declare -a subarray=([0]="one" [1]="two")

subarray=("${myarray[@]:1:3}")
declare -p subarray
# => declare -a subarray=([0]="two" [1]="three" [2]="four")

Wenn du den Längen-Teil weglässt, bedeutet das „vom Offset bis zum Ende des Arrays“:

subarray=("${myarray[@]:2}")
declare -p subarray
# => declare -a subarray=([0]="three" [1]="four")

Ein Array an eine Funktion übergeben

Das ist nicht so unkompliziert wie in anderen Sprachen, die du vielleicht kennst. Es gibt zwei grundlegende Techniken, ein Array an eine Funktion zu übergeben.

Die Elemente übergeben

Bei der ersten Technik übergibst du alle Werte des Arrays und sammelst sie in der Funktion in einem lokalen Array.

myfunc() {
    local array_copy=("$@")
    # do stuff with array_copy
    declare -p array_copy
}

array_original=(11 22 33 44)
myfunc "${array_original[@]}"

Das Array der Funktion enthält eine Kopie der Werte. Änderungen, die in der Funktion am Array vorgenommen werden, wirken sich nicht auf den äußeren Gültigkeitsbereich aus.

Den Namen des Arrays übergeben

Diese Technik ähnelt eher der Möglichkeit der „Übergabe als Referenz“, die du aus anderen Sprachen kennst. Du übergibst den Namen des Arrays als String. Die Funktion erstellt eine lokale Variable mit dem Attribut „nameref“. Dieses lokale Array und das globale Array (dessen Namen wir übergeben haben) sind dasselbe Array.

myfunc() {
    # note the `-n` option
    local -n local_array=$1

    # do stuff with local_array
    for i in "${!local_array[@]}"; do
        printf '%d => %s\n' "$i" "${local_array[i]}"
    end

    # we can mutate it
    local_array+=(55 66 77)
}

array_original=(11 22 33 44)
myfunc "array_original"

# show the mutated array
declare -p array_original
# => declare -a array_original=([0]="11" [1]="22" [2]="33" [3]="44" [4]="55" [5]="66" [6]="77")

Namerefs funktionieren auch mit assoziativen Arrays und mit „skalaren“ Variablen (die einen String-Wert enthalten).

Note

Innerhalb der Funktion ist declare -p local_array nicht besonders hilfreich. Sie gibt nur declare -n local_array="array_original" aus. Detaillierte Informationen über das Array bekommst du, wenn du den übergebenen Array-Namen untersuchst: declare -p "$1"

Caution

Achte darauf, dass das lokale Array einen anderen Namen hat als das übergebene Array. Der Code funktioniert trotzdem, aber er gibt Warnungen wie „circular name reference“ aus:

myfunc() {
    local -n a=$1
    local IFS=,
    echo "${a[*]}"
}

# same name as the function's local variable
a=(one two three)
myfunc a
bash: local: warning: a: circular name reference
bash: warning: a: circular name reference
bash: warning: a: circular name reference
bash: warning: a: circular name reference
one,two,three

Die Positionsparameter sind „array-ähnlich“

In Shells, die nur dem POSIX-Standard entsprechen wollen (wie ash und dash), gibt es keine Arrays. Am nächsten kommst du heran, wenn du die Positionsparameter verwendest.

  • Auf die Positionsparameter greifst du über den Index zu: $1, $2 usw.
  • Mit "$@" werden sie in einzelne Elemente expandiert
  • Mit "$*" werden sie zu einem einzigen String zusammengefügt
  • Die Anzahl der Parameter ist $#

Mit dem Befehl set weist du ihnen Werte zu:

set -- one two three
set -- "$@" four

for item in "$@"; do
    echo "do something with $item"
done

Wenn dein Ziel ist, „portable“ Shell-Skripte zu schreiben, verwendest du die Positionsparameter, um eine „Liste“ von Werten zu speichern.

Über GitHub bearbeiten Der Link öffnet sich in einem neuen Fenster oder Tab