ubuntuusers.de

Arrays übergeben

Status: Ungelöst | Ubuntu-Version: Ubuntu 10.04 (Lucid Lynx)
Antworten |

henry06

Anmeldungsdatum:
19. November 2007

Beiträge: 51

Hallo liebe Mitmenschen und Mitmenschinen,

ich hab mal ne Frage - ich bastle gerade an einem bash Skript und stelle fest, dass es inzwischen über 200 Zeilen lang geworden ist (ohne Kommentare und mit nur wenigen Leerzeilen) und wird sicher noch weiter wachsen.

Eigentlich würde ich gerne gewissen Quelltext in andere Skripte auslagern, also sozusagen ein Hauptskript, welches dann Unterskripts aufruft und sich deren Ergebnisse zurückgeben lässt. (Damit die einzelnen Skripte übersichtlich bleiben)

Dabei sollen diese Unterskripte des Öfteren Arrays erzeugen und diese dann an das Hauptskript übergeben.

Kann ich denn, wenn ich z.B.

1
2
#!/bin/bash
./unterskript.sh

aufrufe, mir Ergebnisse (z.B. Arrays) wiedergeben lassen? "return array" wie in Java geht ja bei bash nicht. Hab ich also andere Möglichkeiten, um komplexere Konstrukte wie Arrays von einem Skript ans andere übergeben zu lassen?

mfg henry

Vain

Avatar von Vain

Anmeldungsdatum:
12. April 2008

Beiträge: 2510

Servus,

nein, hast du nicht. Du kannst nur genau ein Array übergeben und das ist das implizite Array der Aufrufargumente.

1
2
3
4
#!/bin/bash

foo=(hallo welt und so)
./unterskript.sh "${foo[@]}"

Aber du bekommst kein Array mehr vom Unterskript ins Hauptskript zurück. Du könntest allenfalls das Unterskript in derselben Shell laufen lassen, sodass de facto kein neuer Prozess erzeugt wird:

1
2
3
4
#!/bin/bash

foo=(hallo welt)
. ./unterskript.sh

Dein Unterskript würde dann direkt auf „$foo“ arbeiten, weil das in derselben Shell läuft. Das muss dann auch nicht mehr übergeben werden.

Aber ganz ehrlich: Wenn du an diesem Punkt angelangt bist und insbesondere „komplexe“ Datenstrukturen benötigst, dann solltest du dir vielleicht doch langsam Gedanken darüber machen, ob die Shell das richtige Werkzeug ist. Ab diesem Punkt arbeitest du eigentlich gegen die Shell und nicht mit ihr, da sie nicht für solche Aufgaben gemacht ist.

Inkane

Anmeldungsdatum:
17. Oktober 2010

Beiträge: 306

Du könntest evtl. die Elemente des Array in eine Datei schreiben und dann die Datei im Hauptskript auslesen. Allerdings sehe ich es auch eher so wie Vain:

Aber ganz ehrlich: Wenn du an diesem Punkt angelangt bist und insbesondere „komplexe“ Datenstrukturen benötigst, dann solltest du dir vielleicht doch langsam Gedanken darüber machen, ob die Shell das richtige Werkzeug ist. Ab diesem Punkt arbeitest du eigentlich gegen die Shell und nicht mit ihr, da sie nicht für solche Aufgaben gemacht ist.

Vain

Avatar von Vain

Anmeldungsdatum:
12. April 2008

Beiträge: 2510

Inkane schrieb:

Du könntest evtl. die Elemente des Array in eine Datei schreiben und dann die Datei im Hauptskript auslesen.

Jo, möglich, aber dann kann er es auch direkt an sein Unterskript pipen. In beiden Fällen wäre es notwendig, die Elemente mit Null-Bytes zu trennen, damit das halbwegs sauber ist. Und, mal ehrlich, sowas will man einfach nicht machen:

haupt.sh:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
#!/bin/bash

foo=(hallo welt $'und\nso\nweiter' blabla)

bar=()
while read -rd '' item
do
	bar+=("$item")
done < <(for i in "${foo[@]}"; do printf "%s\0" "$i"; done | ./unter.sh)

for i in "${bar[@]}"
do
	echo "[$i]"
done

unter.sh:

1
2
3
4
5
6
#!/bin/bash

while read -rd '' item
do
	printf "test: %s\0" "$item"
done

In haupt.sh ist ein Array definiert mit ein paar Elementen. Es „übergibt“ das Ding dann an unter.sh, was jedem dieser Elemente ein test: voranstellt. Dann die „Rückgabe“ und in haupt.sh am Ende die Ausgabe des neuen Arrays. Der Zeilenumbruch in einem der Array-Elemente soll zeigen, weshalb das Null-Byte als Trenner notwendig ist.

Wie oben geschrieben könnte man die Übergabe an das Unterskript auch kürzer machen, aber die „Rückgabe“ muss so sein. Da steckt mehr Komplexität in der Array-Wurschtelei als in der eigentlichen Funktionalität.

henry06

(Themenstarter)

Anmeldungsdatum:
19. November 2007

Beiträge: 51

Vain schrieb:

Servus,

nein, hast du nicht. Du kannst nur genau ein Array übergeben und das ist das implizite Array der Aufrufargumente.

Das man so Strings und dergleichen übergeben kann, war mir schon klar, aber kann ich denn tatsächlich das komplette Array übergeben?

Ich mein, ich hab das zwar nicht gefragt, aber gebrauchen könnte ich das schon, wenn das funktionieren würde.

Ich hab mal folgendes getestet:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
#!/bin/bash

#haupt.sh

schritte="0"
array[0]="empty"
while [ $schritte -le "15" ]
do
        array[$schritte]="Schritt:\ "$schritte
        ((schritte ++))
done
./unter.sh "${array[@]}"
1
2
3
4
5
6
#!/bin/bash

#unter.sh

array=($@)
echo "${array[4]}"

Als Ausgabe habe ich aber statt "Schritt: 4" nur

1
Schritt:\

bekommen. Kannst Du mir eventuell noch ein Tipp geben, wie ich im Unterskript das Array noch aufnehmen kann? Mit "array=$1" oder dergleichen, wie es bei einfachen Strings funktionieren würde, bekomme ich nur den String bis zum ersten Leerzeichen. Auch wenn ich das Leerzeichen maskiere (wie oben geschehen) hilft das nicht.

Aber ganz ehrlich: Wenn du an diesem Punkt angelangt bist und insbesondere „komplexe“ Datenstrukturen benötigst, dann solltest du dir vielleicht doch langsam Gedanken darüber machen, ob die Shell das richtige Werkzeug ist. Ab diesem Punkt arbeitest du eigentlich gegen die Shell und nicht mit ihr, da sie nicht für solche Aufgaben gemacht ist.

Also wie gesagt, ich könnte das alles in einem Skript schreiben, das wird dann zwar vermutlich bis zu 500 Zeilen lang und dadurch etwas unübersichtlich, aber funktionieren tuts bislang zumindest super (erfüllt seine Aufgabe und scheint kaum rechenintensiv zu sein, jedenfalls ist das Skript auf meinen Rechner immer sofort fertig mit Rechnen)

Ziel des Teilens des Skriptes ist ja eigentlich nur, eine gewissen Übersichtlichkeit für mich zu erhalten und teilweise auch bestimmten Code mehrmals/wieder zu verwenden. Nötig wäre es nicht. Allerdings hast Du mich auf eine Frage gebracht, die ich schon lange mal geklärt haben wollte. Hab dafür einen neuen Thread verwendet, um "Thread-Hijacking", was laut Forenregeln verboten ist, zu vermeiden.

mfg henry

henry06

(Themenstarter)

Anmeldungsdatum:
19. November 2007

Beiträge: 51

Vain schrieb:

Inkane schrieb:

Du könntest evtl. die Elemente des Array in eine Datei schreiben und dann die Datei im Hauptskript auslesen.

Jo, möglich, aber dann kann er es auch direkt an sein Unterskript pipen. In beiden Fällen wäre es notwendig, die Elemente mit Null-Bytes zu trennen, damit das halbwegs sauber ist. Und, mal ehrlich, sowas will man einfach nicht machen: [...] Da steckt mehr Komplexität in der Array-Wurschtelei als in der eigentlichen Funktionalität.

Nachdem ich so allmählich verstehen zu scheine, wie das funktionieren soll, sehe ich das ähnlich. Ich würde so ja Rechengeschwindigkeit einbüßen, und das sollte eigentlich soweit wie möglich vermieden werden.

Auf die Idee von Inkane bin ich auch schon gekommen, allerdings stelle ich mir das auch Rechenaufwendig vor, wenn man erst eine *.txt Datei anlegt und diese wiederausliest.

In einem anderen Zusammenhang kann ich mir so etwas auch vorstellen, aber für den Zweck, den ich hier hab, wäre es wohl unsinnig.

Das heißt dann wohl, dass ich aufs "Array übergeben" in Bashskripten verzichten werde.

mfg henry

objective

Anmeldungsdatum:
12. Oktober 2012

Beiträge: Zähle...

Schon ein alter Beitrag, aber vielleicht hilft es ja noch jemanden....

Teste doch mal Folgendes...

Der Aufruf war schon ok so, nur es wurde "Schritt: \" mit in das Array übergeben, das Array wurde nur nicht wieder genau so aufgerufen, daher keine Werte bei der Rückgabe...

henry06

(Themenstarter)

Anmeldungsdatum:
19. November 2007

Beiträge: 51

Für die Aufgabe, die ich damals lösen wollte, nutze ich inzwischen Java. Die Bash - es wurde in dem Thread ja bereits angesprochen - ist bei solchen Aufgaben einfach überfordert.

mfg henry

Antworten |