ubuntuusers.de

bash, Array vergisst frühere Werte

Status: Gelöst | Ubuntu-Version: Ubuntu 19.10 (Eoan Ermine)
Antworten |

Theo.Spengler

Anmeldungsdatum:
4. Januar 2019

Beiträge: 57

Ich habe in bash ein array welches die früheren Werte vergisst.

Besagtes Array befindet sich in einer Schleife, bei jedem Schleifendurchlauf soll ihm ein Wert hinzu gefügt werden.

1
hier muss ich noch meinen Code heraus suchen

Nun habe ich getestet ob ich es an hand eines Beispiels ohne das sich das Array in einer Schleife befindet hin bekomme ein Array zu erzeugen und ihm nacheinander je einen Wert hinzu zu fügen. Und das geht schon mal:

 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
#!/bin/bash

var_a=Diesel
var_b=Zweitakter
var_c=hallo_12345

echo testvariante_001
my_array=(123 abc)
my_array+=(1bc)
echo "${my_array[@]}"
echo
echo

echo testvariante_002
my_array=($var_a $var_b)
my_array+=($var_c)
echo "${my_array[@]}"
echo
echo

echo testvariante_003
my_array=($var_a)
my_array=($my_array $var_b)
my_array+=($var_c)
echo "${my_array[@]}"
echo
echo

read -p "Zum Beenden Enter drücken oder Ctl + C"

Gibt es bei dem Betrieb eines Arrays in einer Schleife Besonderheiten um einen Arrayinhalt von einer Schleife in die nächste zu retten ?

Ich glaub ich habe da mittlerweile eine Vermutung: * Ist es s das das wenn ich folgendes schreibe, der alte Inhalt eines Array gelöscht wird?

1
my_array=(123_abc)

Und das damit keine alten Werte eines Arrays überschrieben werden, man auch den ersten Wert im Array so ein fügen muss wie bei Einfügen eines Folgewertes ?

1
my_array+=(123_abc)

Vain

Avatar von Vain

Anmeldungsdatum:
12. April 2008

Beiträge: 2510

Wahrscheinlich läuft dein Schleifenrumpf in einer Subshell. Sowas in der Richtung (gibt „1 2 3“ aus):

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

foo=(1 2 3)

date | while read something
do
    foo+=("$something")
done

echo "${foo[@]}"

Die Schleife läuft in einem anderen Prozess und hat damit keine Auswirkungen auf dein „Hauptprogramm“. (Sprenkel mal ein paar „echo $BASHPID“ ein, dann sieht man es.)

Wie genau man damit am besten umgeht, hängt von deinem konkreten Code ab.

Theo.Spengler

(Themenstarter)

Anmeldungsdatum:
4. Januar 2019

Beiträge: 57

Vain schrieb:

foo=(1 2 3)

Sag mal, die immer mal wieder hier und da auf tauchende Bezeichnung "foo", ist die eine Abkürzung für irgend etwas wie "Hello World" ?

Vain

Avatar von Vain

Anmeldungsdatum:
12. April 2008

Beiträge: 2510

Theo.Spengler schrieb:

Vain schrieb:

foo=(1 2 3)

Sag mal, die immer mal wieder hier und da auf tauchende Bezeichnung "foo", ist die eine Abkürzung für irgend etwas wie "Hello World" ?

Das ist ein sehr häufig verwendeter Platzhalter für irgendwas, dessen Namen gerade keine Rolle spielt: https://en.wikipedia.org/wiki/Foobar

Doc_Symbiosis

Avatar von Doc_Symbiosis

Anmeldungsdatum:
11. Oktober 2006

Beiträge: 4453

Wohnort: Göttingen

Naja, foobar ist nicht ganz so etwas wie Hallo Welt, sondern einfach ein Platzhalter: https://de.wikipedia.org/wiki/Fubar

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13211

Theo.Spengler schrieb:

1
hier muss ich noch meinen Code heraus suchen

Das ist wirklich wichtig, dass Du den Code zeigst, um den es wirklich geht. Sonst raten wir hier nur rum.

* Ist es s das das wenn ich folgendes schreibe, der alte Inhalt eines Array gelöscht wird?

1
my_array=(123_abc)

Natürlich, Du weist alles, was rechts steht, der Variable zu. Damit geht alles verloren, was die Variable vorher enthalten hat.

Und das damit keine alten Werte eines Arrays überschrieben werden, man auch den ersten Wert im Array so ein fügen muss wie bei Einfügen eines Folgewertes ?

1
my_array+=(123_abc)

Wenn schon Werte im Array sind, ist es ja nicht der erste Wert. Falls Du vom ersten Schleifendurchlauf sprichst, klar, dann ist es das einfachste immer += zu verwenden, weil man dann den ersten Durchlauf nicht von den folgenden unterscheiden muss. Z.B.

1
2
3
4
5
6
7
8
9
array=()

for arg in *; do
  array+=("$arg")
done

# ist übrigens dasselbe wie
array=(*)
# aber das nur nebenbei

Logischerweise geht immer alles verloren, wenn Du im Schleifenrumpf = benutzt. Zeig halt Deinen Code.

Theo.Spengler

(Themenstarter)

Anmeldungsdatum:
4. Januar 2019

Beiträge: 57

rklm schrieb:

Theo.Spengler schrieb:

1
hier muss ich noch meinen Code heraus suchen

Das ist wirklich wichtig, dass Du den Code zeigst, um den es wirklich geht. Sonst raten wir hier nur rum.

Das der Inhalt des Arrays bei mir von einem Schleifendurchlauf zum nächsten verloren geht, war ein Irrtum. Dieser rührte daher, das ich die Echo Ausgabe an nahe liegender Codestelle falsch interpretiert habe und die Echoausgabe an der eigentlichen Stelle wegen eines Syntax Fehlers garnicht erfolgte.

Nun ist es so, das ich noch eine Möglichkeit suche, das Array nach letzten Durchlauf zu leeren oder zu löschen, weil ich das als saubere Methode empfinde, als das wie ich es im Moment mache. Im Moment Lösche ich das Array vor dem Schleifenaufruf, so das vor diesem Zeitpunkt, sozusagen unnötig ungelöschte Daten im Speicher rum lungern. Evtl. sehe ich das da aber auch unangemessen streng.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
counter=0 # gewünschter Startwert des Zählers
#runs=10000 # Anzahl gewünschter Schleifendurchläufe
limited=true # false = Enlosschleife, true = keine Endlosschleife
unset my_array # Array löschen. Ersteinmal hilfsweise vor dem Gebrauch. Am besten jedoch nach dessen Gebrauch.
while(true);do
    [ $limited == true ] && [ $((runs--)) -eq 0 ] && break
     counter=$((counter+1))

my_array+=("${anderes_array[$array_stelle]}") # my_array einen Wert hinzu fügen
echo ${my_array[@]}

     echo $counter
done

read -p "Zum Beenden Enter drücken oder Ctl + C"

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13211

Theo.Spengler schrieb:

Nun ist es so, das ich noch eine Möglichkeit suche, das Array nach letzten Durchlauf zu leeren oder zu löschen, weil ich das als saubere Methode empfinde, als das wie ich es im Moment mache. Im Moment Lösche ich das Array vor dem Schleifenaufruf, so das vor diesem Zeitpunkt, sozusagen unnötig ungelöschte Daten im Speicher rum lungern. Evtl. sehe ich das da aber auch unangemessen streng.

Das ergibt keinen Sinn. Entweder Du willst das Array vor der Benutzung leeren oder löschen, damit Du von einem definierten Ausgangszustand ausgehst. Oder Du willst das Array nach Benutzung leeren oder löschen, damit es keinen Platz braucht, sensible Daten festhält oder sonst etwas. Oder beides. Aber vorher und nachher löschen verfolgen ja völlig unterschiedliche Ziele und sind deshalb keine Alternativen.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
counter=0 # gewünschter Startwert des Zählers
#runs=10000 # Anzahl gewünschter Schleifendurchläufe
limited=true # false = Enlosschleife, true = keine Endlosschleife
unset my_array # Array löschen. Ersteinmal hilfsweise vor dem Gebrauch. Am besten jedoch nach dessen Gebrauch.
while(true);do
    [ $limited == true ] && [ $((runs--)) -eq 0 ] && break
     counter=$((counter+1))

my_array+=("${anderes_array[$array_stelle]}") # my_array einen Wert hinzu fügen
echo ${my_array[@]}

     echo $counter
done

read -p "Zum Beenden Enter drücken oder Ctl + C"

Das doppelte Gleichheitszeichen ist da falsch. Dafür brauchst Du die doppelten eckigen Klammern. Mit einfachen nimmst Du auch nur ein Gleichheitszeichen. Ich würde mindestens die Schleifenbedingung hinter while packen, damit klarer ist, was Du da vorhast.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
#runs=10000 # Anzahl gewünschter Schleifendurchläufe
limited=true # false = Enlosschleife, true = keine Endlosschleife
unset my_array # Array löschen. Ersteinmal hilfsweise vor dem Gebrauch. Am besten jedoch nach dessen Gebrauch.

while [ $limited = false ] || [ $((runs--)) -gt 0 ]; do
  counter=$((counter+1))

  my_array+=("${anderes_array[$array_stelle]}") # my_array einen Wert hinzu fügen
  echo ${my_array[@]}
  echo $counter
done

read -p 'Zum Beenden Enter drücken oder Ctl + C'

Man könnte es aber auch davon abhängig machen, ob $runs gesetzt ist:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
#runs=10000 # Anzahl gewünschter Schleifendurchläufe oder leer lassen für endlos
unset my_array # Array löschen. Ersteinmal hilfsweise vor dem Gebrauch. Am besten jedoch nach dessen Gebrauch.

while [ -z "$runs" ] || [ $((runs--)) -gt 0 ]; do
  counter=$((counter+1))

  my_array+=("${anderes_array[$array_stelle]}") # my_array einen Wert hinzu fügen
  echo ${my_array[@]}
  echo $counter
done

read -p 'Zum Beenden Enter drücken oder Ctl + C'
Antworten |