ubuntuusers.de

Array in for-Schleife auslesen

Status: Ungelöst | Ubuntu-Version: Ubuntu 9.04 (Jaunty Jackalope)
Antworten |

corubba

Anmeldungsdatum:
18. Januar 2009

Beiträge: Zähle...

Hey Jungs und Mädels,

mein Problem dreht sich um folgenden Codeschippsel:

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

ar_1=(	490	480	685 )
ar_2=(	680	200	600 )
ar_3=( "hallo" "du" )

for ((i=1;i<=3;i++)); do
	name=ar_$i
	echo ${!name[0]}
	echo ${!name[1]}
done

Die Ausgabe dazu:

user@machine:~$ bash /home/user/stuff/test.sh
490

680

hallo

user@machine:~$ 

Vorher hatte ich es mit echo ${ar_${i}[0] probiert, da kam nur ein ${ar_${i}[0]}: bad substitution raus. Ich möchte nichts anderes als in der Schleife auf die Daten im Array auch array-like zugreifen. Hat da jmd. vllt. eine Idee wie man das machen könnte? Btw: Bin noch relativ unerfahren im Shell-Scripting. Ich danke schonmal herzlichst im Vorraus.

Greetz corubba

tulpi

Anmeldungsdatum:
26. April 2007

Beiträge: Zähle...

Ich hab nur diesen Schnippsel und der funktioniert auch 😬 Hab sonst keine Ahnung Grüße

1
2
3
4
5
kartenzielordnert=( "eins" "zwei" "drei")
for((u=0;u<${#kartenzielordnert[*]};u++))
do
    echo "${kartenzielordnert[$u]}"
done

Vain

Avatar von Vain

Anmeldungsdatum:
12. April 2008

Beiträge: 2503

Hallo corubba,

im Prinzip willst du doch „nested arrays“ haben, oder? Also deine Struktur samt Ausgabe sähe in PHP so aus:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
$gesamt = array(
	array(490, 480, 685),
	array(680, 200, 600),
	array("hallo", "du")
);

foreach ($gesamt as $subarray)
{
	foreach ($subarray as $element)
	{
		echo $element."\n";
	}
	echo "\n";
}

Bin ich so weit erstmal auf dem richtigen Dampfer? Denn falls ja, dann kriegst du das so in der Bash nur mit großen Umwegen hin, soweit ich weiß. Vielleicht mit sowas wie IFS- oder eval-Tricksereien, aber von „Array“ kann da keine große Rede mehr sein (außerdem recht fehleranfällig):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
#!/bin/bash

arr_1="490;480;685"
arr_2="680;200;600"
arr_3="hallo;du"

gesamt=("$arr_1" "$arr_2" "$arr_3")

for sub in "${gesamt[@]}"
do
	OLD_IFS="$IFS"
	IFS=";"

	for i in $sub
	do
		echo "$i"
	done
	echo ""

	IFS="$OLD_IFS"
done

Nebenbei: Du kannst PHP auch für normale Skripte verwenden, falls du das unbedingt möchtest:

1
2
3
4
#!/usr/bin/env php
<?php

echo "Hallo, Welt!\n";

Das kannst du dann ausführbar machen und normal starten, falls PHP entsprechend installiert ist.

Trotzdem: Ich bin zwar auch ein Fan von Shellskripten, aber benötigst du hier tatsächlich mehrdimensionale Arrays in einem solchen? Vielleicht schaust du dich noch anderweitig mal ein bisschen um. Ab einer gewissen Komplexität wird’s in der Bash einfach „anstrengend“. ☺

Hello_World

Anmeldungsdatum:
13. Juni 2006

Beiträge: 3620

In dem Moment, wo Du verschachtelte Arrays brauchst, ist es an der Zeit, zu einer anderen Sprache zu wechseln. PHP solltest Du dabei aus Gründen, die in diesem Forum schon vielfach diskutiert wurden, nach Möglichkeit vermeiden. Die üblichen Kandidaten sind Python, Perl und Ruby. In Python:

1
2
3
4
5
ar = [[490, 480, 685], 
      [680, 200, 600],
      ["hallo", "du"]]
for x in ar:
    print ar[0],'\n',ar[1]

oder Perl:

1
2
3
4
5
my @ar = ([490, 480, 685],
          [680, 200, 600],
          [qw(hallo du)]);

print "$_->[0]\n$_->[1]\n" for (@ar);

tulpi

Anmeldungsdatum:
26. April 2007

Beiträge: 100

Ich glaube das geht nicht richtig mit der bash, da hierbei etwas mit der hash-Table nicht stimmt. Das Array liegt nicht in der richtigen Reihenfolge im Arbeitsspeicher vor. Ich glaub beim Array "initialisieren??" wird es so in den Arbeitsspeicher geworfen um Speicherlücken zu vermeiden und dabei kommt die Reihenfolge durcheinander mit der bash.

cyrex

Anmeldungsdatum:
20. Oktober 2007

Beiträge: 221

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

ar_1=(	490	480	685 )
ar_2=(	680	200	600 )
ar_3=( "hallo" "du" "nuss" )

for ((i=1;i<=3;i++)); do
     name=ar_$i
     for ((j=1;j<=${#name[*]};j++)); do
	echo ${name[j]}
     done
done

Ausgabe:

1
2
3
4
5
6
7
8
9
490
480
685
680
200
600
hallo
du
nuss

Hello_World

Anmeldungsdatum:
13. Juni 2006

Beiträge: 3620

@cyrex: Dein Code kann nicht funktionieren und gibt bei mir auch überhaupt nichts aus.

cyrex

Anmeldungsdatum:
20. Oktober 2007

Beiträge: 221

Hmmm kanns nicht probieren aber sollte eigentlich funktionieren. Kann sein das ich die Syntax nicht richtig habe. Aber der logische Ansatz stimmt zumindest 😛.

Wenn ein Fehler drin ist bitte einfach korrigieren ... bin mit der Syntax von Bash nicht so stark vertraut ☺.

Aber logisch sollte es korrekt sein.

- Erzeugt werden drei arrays

- zähle i von 1 bis 3

- setze name = ar_$i (ar_1, ar_2, ar_3)

- zähle j von 1 bis zur größe von name (immer das aktuelle array)

- gebe jedes element im aktuellen array aus

- beende innere schleife

- äußere führt fort bis i = 3

Ich könnts jetzt schnell in Java schreiben 😛 aber damit ist dem Threadstarter leider nicht geholfen.

Hello_World

Anmeldungsdatum:
13. Juni 2006

Beiträge: 3620

cyrex schrieb:

Hmmm kanns nicht probieren aber sollte eigentlich funktionieren. Kann sein das ich die Syntax nicht richtig habe. Aber der logische Ansatz stimmt zumindest 😛.

Nein, er stimmt nicht. echo ${name[j]} gibt das j-te Element des Arrays name aus, nicht das j-te Element des Arrays, dessen Name in der Variablen name gespeichert ist, entsprechend kann das nicht funktionieren.

Um auf den Inhalt der Variablen zuzugreifen, deren Name in der Variablen x gespeichert ist, gibt es in der bash das Konstrukt ${!x}. Das lässt sich aber nicht vernünftig auf Arrays übertragen, denn ${!x[i]} liefert den Wert der Variablen, deren Name im i-ten Element des Arrays x gespeichert ist, und nicht das i-te Element des Arrays, dessen Name in der Variablen x gespeichert ist, wie man es hier bräuchte. Und damit bist Du geplatzt.

Die Konsequenz ist, bash nicht zum Scripten zu verwenden, sondern eine der bereits erwähnten Sprachen Ruby, Python oder Perl. sh und bash gibt es eigentlich nur noch aus historischen Gründen.

cyrex

Anmeldungsdatum:
20. Oktober 2007

Beiträge: 221

Mag sein das es die Eigenart von Bash ist bei einem Zuweisungsoperator statt den Werten nur die Namen zu übergeben 😛 ... das kann aber auch kein Mensch ahnen 😛.

@corubba

Ich kann sowieso nur dazu Raten mal Ruby genauer unter die Lupe zu nehmen. Ist was sehr sehr feines ☺ http://tryruby.org/

@Hello World

Ich kann Leute nicht ausstehen die mir gegenüber arrogant auftreten. Belehren lasse ich mich gerne wenn ich Fehler mache aber sowas wie "Und damit bist Du geplatzt" kannst du dir sparen. Das hier ist ne Community ... denk mal drüber nach.

corubba

(Themenstarter)

Anmeldungsdatum:
18. Januar 2009

Beiträge: 19

Heyho, danke erstmal für die Hilfe und die ganzen Ideen.

In PHP hätt ich das ganze in nichtmal 5min selber schreiben können ^^ Ich wollte das eigentlich vermeiden auf eine andere Scriptsprache zurückzugreifen einfach aus dem Grund, das ich Befehle über die System-Shell verwenden muss, da es keine Scriptsprache gibt die auf Systemdienste zugreifen bzw. diese beeinflussen kann, und auch nicht sollte.

Ich werd wohl die unübersichtliche Variante nehmen und jeden wert in eine eigene Variable speichern, ohne Arrays. Das müsste ja dann eigentlich funktionieren. Trotzdem danke für die Bemühungen. Ich meld mich wenns neue Erkenntnisse gibt.

Greetz corubba

Hello_World

Anmeldungsdatum:
13. Juni 2006

Beiträge: 3620

corubba schrieb:

In PHP hätt ich das ganze in nichtmal 5min selber schreiben können ^^ Ich wollte das eigentlich vermeiden auf eine andere Scriptsprache zurückzugreifen einfach aus dem Grund, das ich Befehle über die System-Shell verwenden muss, da es keine Scriptsprache gibt die auf Systemdienste zugreifen bzw. diese beeinflussen kann, und auch nicht sollte.

Die Shell ist unter Unix ein Prozess wie jeder andere, daher ist es schlicht falsch, dass man mit Python & Co. nicht auf Systemdienste zugreifen und diese beeinflussen könne.

Sid_Burn

Anmeldungsdatum:
23. Oktober 2004

Beiträge: 2159

@Hello World Ich kann Leute nicht ausstehen die mir gegenüber arrogant auftreten. Belehren lasse ich mich gerne wenn ich Fehler mache aber sowas wie "Und damit bist Du geplatzt" kannst du dir sparen. Das hier ist ne Community ... denk mal drüber nach.

Ich finde "Hello, World!" ist nichtmal ansatzweise arrogant gewesen. Ich frage mich aber was das ein verhalten von dir ist, du hast offensichtlichen Code geliefert der nicht funktionierte. Es wurde darauf hingewiesen das er nicht geht und das der Code nichts ausgiebt. Du der nichtmal seinen eigenen Code getestet hat willst darauf nicht hören und meinst immer noch felsenfest davon überzeugt das es ja gehen müsste, ohne das es mal selber probierst. Danach noch zu behaupten "Hello World" wäre arrogant weil er dir genau erklärt warum es nicht geht ist schon ziemlich frech. Vielleicht solltest mal selber über deinen letzten satz nachdenken, und überdenken wie man mit anderen umgeht.

Ich wollte das eigentlich vermeiden auf eine andere Scriptsprache zurückzugreifen einfach aus dem Grund, das ich Befehle über die System- Shell verwenden muss, da es keine Scriptsprache gibt die auf Systemdienste zugreifen bzw. diese beeinflussen kann, und auch nicht sollte.

Die Bash oder die Shell im allgemeinen führt letztendlich nur fremde Programme aus. Du kannst jedes fremde Programm auch in Programmiersprachen wie Perl, Python oder Ruby aufrufen. Hierfür gibt es meist etliche ausführungsarten. Dazu kommt dann aber noch das für manche Programme Wrapper geschrieben wurden, sogenannte Bibliotheken das den umgang mit fremd Programmen vereinfacht. Oder aber es gibt andere Möglichkeiten mit bestimmten Diensten zu sprechen. Andere wege die weniger fehlerträchtig sind, zum Beispiel über DBus, Sockets oder andere Kommunikationsmöglichkeiten. Zumindest sehe ich nicht was du befürchtigung hast. Alles was in der Shell geht, geht letztendlich auch in einer der genannten Programmiersprachen.

Und warum diese Programmiersprachen "Systemdienste" nicht verändern sollten ist mir auch ein rätsel.

cyrex

Anmeldungsdatum:
20. Oktober 2007

Beiträge: 221

Sid Burn schrieb:

Ich finde "Hello, World!" ist nichtmal ansatzweise arrogant gewesen. Ich frage mich aber was das ein verhalten von dir ist, du hast offensichtlichen Code geliefert der nicht funktionierte. Es wurde darauf hingewiesen das er nicht geht und das der Code nichts ausgiebt. Du der nichtmal seinen eigenen Code getestet hat willst darauf nicht hören und meinst immer noch felsenfest davon überzeugt das es ja gehen müsste, ohne das es mal selber probierst. Danach noch zu behaupten "Hello World" wäre arrogant weil er dir genau erklärt warum es nicht geht ist schon ziemlich frech. Vielleicht solltest mal selber über deinen letzten satz nachdenken, und überdenken wie man mit anderen umgeht.

Alles was du gerade geschrieben hast ist schlichtweg gelogen oder du hast alles vor dem letzten Post von mir nicht gelesen.

1. War ich nicht felsenfest überzeugt, denn ich habe geschrieben "Wenn ein Fehler drin ist bitte einfach korrigieren"

2. Habe ich gesagt das ich mit der Bash nicht sehr vertraut bin und daher lediglich gesagt habe das der logische Ansatz stimmt (und das tut er nach wie vor, feinheiten wie die Zuweisung von Arrays in der Bash wusste ich einfach nicht und das ist auch ok wenn ich da eines besseren belehrt werde, nur so kann man lernen).

3. Finde ich nicht die Erklärung von Hello World arrogant (dafür bin ich sogar sehr dankbar da ich nun wieder was gelernt habe), sondern über die Art und Weise wie die Erklärung geschrieben wurde. Der Ton macht immernoch die Musik.

4. Sollten wir solche privaten Diskussionen bzw. Meinungsverschiedenheiten nicht hier in einem Thread ausufern lassen, der damit nichts zu tun hat, denke ich. Wenn du willst kannst du gerne zu mir auf nen Kaffee vorbeikommen und wir diskutieren das aus 😛.

Hello_World

Anmeldungsdatum:
13. Juni 2006

Beiträge: 3620

Ich empfehle an dieser Stelle die Lektüre des Abschnitts On not reacting like a loser von ESRs Essay "How to ask questions the smart way".

Antworten |