ubuntuusers.de

array in funktion übergeben

Status: Gelöst | Ubuntu-Version: Nicht spezifiziert
Antworten |

FrancisA

Anmeldungsdatum:
11. Dezember 2006

Beiträge: 965

Wohnort: Upper Austria

hier ein kleines codesnippet:

exchange()
{
  my_array=$3
  eval echo "hi" \${$my_array[*]}
  #echo "hi" \${$my_array[*]}

  #echo "hi" ${$3[*]}
  # Swaps two members of the array.
  local temp=${$3[$1]} #  Temporary storage
                              #+ for element getting swapped out.
  &3[$1]=${$3[$2]}

  return
}

exchange $index `expr $index + 1` dir1filearray

es wird immer ein substitutionsfehler angezeigt. Wie muss ich das array übergeben? Wie kann ich das array dann in der funktion exchange dann richtig verwenden bzw. ansprechen?

Danke im voraus,

Vain

Avatar von Vain

Anmeldungsdatum:
12. April 2008

Beiträge: 2503

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:

1
2
3
$ 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

FrancisA

(Themenstarter)

Anmeldungsdatum:
11. Dezember 2006

Beiträge: 965

Wohnort: Upper Austria

Vain schrieb:

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. 😉

Oh das und ist nur ein Schreibfehler, gemeint war natürlich $ 😉 Der Rest: Eine Menge Stoff zum durchlesen, vielen Dank Warum ist das in der bash gegen C++ und Python alles so kompliziert (oder denken die bash erfahrenen genau anders herum?) 😉

Vain

Avatar von Vain

Anmeldungsdatum:
12. April 2008

Beiträge: 2503

FrancisA schrieb:

Warum ist das in der bash gegen C++ und Python alles so kompliziert (oder denken die bash erfahrenen genau anders herum?) 😉

Oh oh, na wenn du da mal keine Grundsatzdiskussion heraufbeschwörst. 😀 Da wir hier vor kurzem erst so einen schönen Thread hatten, gehe ich da mal lieber nicht näher drauf ein. 😉

FrancisA

(Themenstarter)

Anmeldungsdatum:
11. Dezember 2006

Beiträge: 965

Wohnort: Upper Austria

Vain schrieb:

FrancisA schrieb:

Warum ist das in der bash gegen C++ und Python alles so kompliziert (oder denken die bash erfahrenen genau anders herum?) 😉

Oh oh, na wenn du da mal keine Grundsatzdiskussion heraufbeschwörst. 😀 Da wir hier vor kurzem erst so einen schönen Thread hatten, gehe ich da mal lieber nicht näher drauf ein. 😉

Oh, oh, bin schon ruhig, fangen wir das nicht nochmals an ☺

Hello_World

Anmeldungsdatum:
13. Juni 2006

Beiträge: 3620

FrancisA schrieb:

Warum ist das in der bash gegen C++ und Python alles so kompliziert

Weil sich die bash über viele Jahre hinweg aus ihren Vorgängern entwickelt hat, wobei immer nur ein Feature über das andere gestapelt wurde, ohne darüber nachzudenken, ob das Gesamtbild überhaupt noch Sinn ergibt (das tut es kaum noch). Bei Python hat man sich dagegen vorher Gedanken gemacht und konnte zudem auf die Erfahrungen zurückgreifen, die man in den Jahren zuvor mit dynamischen Sprachen gesammelt hatte (die ursprüngliche Bourne-Shell war von '77, Python gibt es erst seit '91)

theinlein

Anmeldungsdatum:
29. Dezember 2007

Beiträge: 1279

Die Shell hat nie zum Ziel gehabt eine Programmiersprache zu sein - Ihr verwechselt da was. Alles, was schon in Richtung Anwendung geht und vernünftige Datenstrukturen braucht, sollte man durch Programmieren in entsprechender Programmiersprache bearbeiten sonst macht man sich Schmerzen.

Die Shell ist ein Kommando-Interpreter, der geeignet ist - statisch gebunden - vom Angebinn des Systemstarts, die notwendigen Hilfsaktionen für das System zu erledigen.

Da die Shell im Frühstadium des Systemstarts einsetzbar mit wenig Abhängigkeiten auskommen soll, war die Integration verschiedener Programme über eine Pipeline und die stdin- und stdout als Standardschnittstelle zwischen den Prozessen eine geniales Konzept.

Typische Systemarbeiten, wie das Schaffen einer geeigneten Laufzeit-Umgebung, Arbeiten im Dateisystem und so Zeug, hat die Shell inne, Schnörkel werden über externe Prozesse eingekauft.

Die ganze Diskussion kommt m.E. davon, dass die Leute das eben mit einer Programmiersprache verwechseln, die eigentliche Zielsetzung und die Historie der Shell nicht gut genug kennen. Wer Shell nicht mag, sollte Esso nehmen 😀 - BP ist ja inzwischen out.

Hello_World

Anmeldungsdatum:
13. Juni 2006

Beiträge: 3620

Fakt ist jedenfalls, dass die Shell heute Kontrollstrukturen usw. hat, die das Wort Programmiersprache rechtfertigen. Daher sollte man regelmäßig darauf hinweisen, dass man für die meisten Programmieraufgaben mit einer anderen Sprache besser bedient ist.

Ich frage mich auch, wie Du zu der Aussage kommst, dass eine Shell für den Systemstart gedacht und geeignet wäre - ich wüsste keinen prinzipiellen Grund, wieso eine Bourne-artige Shell da besser funktionieren sollte als ein Interpreter für eine vernünftige Sprache wie lua. Dass die Shell dafür eingesetzt wird hat doch in erster Linie historische Gründe; früher gab es eben nichts anderes.

FrancisA

(Themenstarter)

Anmeldungsdatum:
11. Dezember 2006

Beiträge: 965

Wohnort: Upper Austria

Ich will mich da nicht einmischen, für mich war die Aufgabenstellung klar. Ich versuche etwas in dieser Sprache umzusetzen (wusste vorher nicht obs so klappt) und das tat es, wenn auch mit einigem Kopfweh. Bei mir sind noch viele Lücken, werde mir ein Tutorial (wie vorher schon gepostet wurde) nochmals überfliegen. Ich stimme zu, bzw. glaube ich, dass die Bash so zu programmieren ist, wie sie ist, weil von Anfang an nicht feststand, was sie in Zukunft alles unterstützen soll, und es nach und nach dazugekommen ist.

Antworten |