Du kannst nur exakt ein Array übergeben und das ist das implizite Array der Argumente an sich. Zurückgeben kannst du gar keines. An dem &
lese ich ab, dass du es irgendwie mit „Pointern“ oder „Referenzen“ versucht hast, was es auch nicht gibt. 😉
Das mit dem impliziten Array meine ich so:
1
2
3
4
5
6
7
8
9
10
11
12 | #!/bin/bash
foo()
{
for i in "$@"
do
echo "[$i]"
done
}
arr=(1 2 3 '4 5 6')
foo "${arr[@]}"
|
Du kannst natürlich immer versuchen, besondere Trennzeichen zu setzen und dann de facto Strings und keine Arrays zu übergeben – mindestens bei der Rückgabe musst du das machen. So umständlich kann das dann werden:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42 | #!/bin/bash
foo()
{
# Schnappe alle Argumente. Muss sein, da $1, $2 usw. nur read-only
# sind. "$@" sind alle Argumente als Array.
myarr=("$@")
# Vertauschen.
tmp="${myarr[3]}"
myarr[3]="${myarr[2]}"
myarr[2]="$tmp"
# Setze IFS auf ein Semikolon um und gib dann das gesamte Array mit
# diesem als Trennzeichen aus. "${foo[*]}" verwendet bei der Ausgabe
# immer das von dir gesetzte IFS, dagegen würde "${foo[@]}" immer
# Leerzeichen verwenden.
IFS=";"
echo "${myarr[*]}"
}
# Initiales Array mit vier Elementen.
arr=(1 2 3 '4 5 6')
# Swappen mithilfe von Funktion und IFS-Gehampel. IFS ist das interne
# Trennzeichen, das die Shell benutzt, um verschiedene Felder zu
# erkennen. Da aus der Funktion ein String (!) herauskommt, der das
# Semikolon als Trenner benutzt, expandiert der Rückgabewert der
# Funktion dann also zu einer Liste, die in "swapped" landet. Wichtig:
# Hinterher immer IFS zurücksetzen.
OIFS="$IFS"
IFS=";"
swapped=($(foo "${arr[@]}"))
IFS="$OIFS"
# Testausgabe des neuen Arrays.
for i in "${swapped[@]}"
do
# Die eckigen Klammern hier dienen nur der Verdeutlichung bei
# der Ausgabe.
echo "[$i]"
done
|
Natürlich knallt das, sobald deine Elemente Semikola enthalten.
Du kannst von einer Funktion aus also nur per Ausgabe (eines Strings) oder per Rückgabewert nach außen kommunizieren, wobei sich der Rückgabewert auf einen Integer beschränkt. Okay, deine Funktion könnte auch auf einer globalen Variablen arbeiten, aber dann könntest du sie dir auch sparen.
Ich weiß, dir geht es ums Lernen – aber im „echten Leben“ würde ich spätestens ab diesem Punkt zu einer anderen Sprache wechseln. ☺
Am Rande: expr
brauchst du zum Rechnen nicht, das geht mit Arithmetic Expansion schöner:
| $ a=3
$ echo $((a + 1))
4
|
-edit:
Du könntest vielleicht noch shift
nutzen. Dann kannst du das so ähnlich machen, wie du dir das dachtest: Die ersten beiden Argumente für die Funktion sind die zu tauschenden Indizes und danach kommt das Array. Aber die restlichen Hässlichkeiten kriegst du meines Wissens nach nicht weg.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49 | #!/bin/bash
foo()
{
# Übernimm die ersten beiden Argumente als Indizes der zu
# tauschenden Elemente und schneide sie dann von der Argumentliste
# ab.
index_a=$1
index_b=$2
shift
shift
# Schnappe alle restlichen Argumente in das lokale Array. Muss sein,
# da $1, $2 usw. nur read-only sind. "$@" sind alle Argumente als
# Array.
myarr=("$@")
# Vertauschen.
tmp="${myarr[$index_a]}"
myarr[$index_a]="${myarr[$index_b]}"
myarr[$index_b]="$tmp"
# Setze IFS auf ein Semikolon um und gib dann das gesamte Array mit
# diesem als Trennzeichen aus. "${foo[*]}" verwendet bei der Ausgabe
# immer das von dir gesetzte IFS, dagegen würde "${foo[@]}" immer
# Leerzeichen verwenden.
IFS=";"
echo "${myarr[*]}"
}
# Initiales Array.
arr=(1 2 3 '4 5 6')
# Swappen mithilfe von Funktion und IFS-Gehampel. IFS ist das interne
# Trennzeichen, das die Shell benutzt, um verschiedene Felder zu
# erkennen. Da aus der Funktion ein String (!) herauskommt, der das
# Semikolon als Trenner benutzt, expandiert der Rückgabewert der
# Funktion dann also zu einer Liste, die in "swapped" landet. Wichtig:
# Hinterher immer IFS zurücksetzen.
OIFS="$IFS"
IFS=";"
swapped=($(foo 2 3 "${arr[@]}"))
IFS="$OIFS"
# Testausgabe des neuen Arrays.
for i in "${swapped[@]}"
do
echo "[$i]"
done
|