• Willkommen im Linux Club - dem deutschsprachigen Supportforum für GNU/Linux. Registriere dich kostenlos, um alle Inhalte zu sehen und Fragen zu stellen.

Variablen in Variablen auflösen

dukenuker

Newbie
Hallo,

ich habe habe folgende Variablen:

MONAT=200601
ANZ_ANZEIGEN=5

Nun möchte ich eine Variable die 200601_5 heißt, erstellen, aber eben dynamisch; also so etwa:

${${MONAT}_${ANZ_ANZEIGEN}}=1

Ich habe eben zwei Variablen, aus deren Inhalten ich einen neuen Variablennamen erstellen will!

Aber das klappt nicht, entweder habe ich bad substitution oder der Inhalt der Variablen ist 200601_5

Weiß jemand Rat?

Viele Grüße,
Simon
 
Hi Simon,
das wird nicht ganz gehen. Variablennamen dürfen nicht mit Ziffern anfangen.
Ansonsten geht es mit "eval", wenn man einfach z.B. den Text "MONAT" am Anfang des Variablennamen einfügt.
Code:
@:~> MONAT=200601
@:~> ANZ_ANZEIGEN=5
@:~>
@:~>
@:~> eval ${MONAT}_${ANZ_ANZEIGEN}=1
bash: 200601_5=1: command not found
@:~> eval MONAT${MONAT}_${ANZ_ANZEIGEN}=1
@:~> echo $MONAT200601_5
1

Haveaniceday
 
OP
dukenuker

dukenuker

Newbie
Danke, das hatte mir bis eben weitergeholfen. Aber ich bekomme Probleme beim Auswerten der Variablen. Ich habe dass Skript mal reingestellt, dann ist glaube ich einfacher zu verstehen, was ich machen will.

Meine Datei sieht so aus:
Code:
20061023    9        4       5        3
20061024    9        7       7        6
20061025   10        5       6        5
20061026   10        6       6        4
20061027   10        6       6        4
20061030    6        4       4        3
20061031    8        5       6        5


Das Skript
Code:
      1 #!/bin/sh
      2
      3 DATEI=$1
      4 LAST_MONAT=189901
      5
      6 while read ZEILE; do
      7         # Das aktuelle Datum; das Skript soll nur bis Ende April laufen (1. Spalte)
      8         AKT_DATE=`echo $ZEILE | awk '{print $1}'`
      9         if      [ $AKT_DATE -ge 20070501 ];then
     10                 break
     11         fi
     12
     13         # Der Aktuelle Monat, falls neu, dann in MONATE speichern (1. Spalte)
     14         AKT_MONAT=`echo $ZEILE | awk '{print substr( $1, 1, 6)}'`
     15
     16         if      [ $AKT_MONAT -gt $LAST_MONAT ]; then
     17                 if      [ -z "$MONATE" ]; then
     18                         MONATE=$AKT_MONAT
     19                 else
     20                         MONATE="$MONATE $AKT_MONAT"
     21                 fi
     22                 LAST_MONAT=$AKT_MONAT
     23         fi
     24
     25         # Hier die Anzahl der Käufe von einer Ware vom akutellen Datum auswählen (2. Spalte)
     26         ANZ=`echo $ZEILE | awk '{print $2}'`
     27
     28         # Falls KAUF_AKT_MONAT[ANZ], also die Anzahl der Käufe einer Ware noch leer ist, dann
     29         # erst auf 1 setzen, beim nächsten Mal wird dann einfach hochgerechnet
     30         if      [ -z \${KAUF_$AKT_MONAT[$ANZ]} ]; then
     31                 eval KAUF_${AKT_MONAT}[${ANZ}]=1
     32         else
     33                 eval KAUF_${AKT_MONAT}[${ANZ}]=2
     34         fi
     35
     36 done < $DATEI

Ab Zeile 29 kriege ich Schwierigkeiten!

Vielen Dank für Hilfe,
Grüße,
Simon
 
Zeile 30: dort wäre ein "eval" notwendig. Hmm, wie ginge das im if ?

Versuch mal statt:
Code:
    30         if      [ -z \${KAUF_$AKT_MONAT[$ANZ]} ]; then
     31                 eval KAUF_${AKT_MONAT}[${ANZ}]=1
     32         else
     33                 eval KAUF_${AKT_MONAT}[${ANZ}]=2
dieses:
Code:
    30         eval let KAUF_${AKT_MONAT}[${ANZ}]+=1

Zum Ausprobieren generell: der "echo" Befehl ist bei Variablen perfekt.

echo ..... => Man sieht was daraus wird.
Bei eval ... nutzt man dann eval echo ....

Viele Grüße,

Haveaniceday

PS: Den Rest des Skripts hab ich mir nicht richtig angeschaut.
Hier eine grobe übersicht: bash biete da Optimierungspotential.

while read AKT_DATE ANZ REST => awk ... $1 und $2 überflüssig.

AKT_MONAT= siehe man bash => ${parameter:eek:ffset:length}
 
OP
dukenuker

dukenuker

Newbie
Wenn ich folgendes codiere:
Code:
	# Falls KAUF_AKT_MONAT[ANZ], also die Anzahl der Käufe einer Ware noch leer ist, dann
	# erst auf 1 setzen, beim nächsten Mal wird dann einfach hochgerechnet
	eval let KAUF_${AKT_MONAT}[${ANZ}]+=1
	eval echo "\$KAUF_${AKT_MONAT}[${ANZ}]"
dann kommt das raus:
Code:
[9]
[9]
[10]
[10]
[10]
[6]
[8]
Es sollte aber das rauskommen:
Code:
2
3
1
1
Zur Erklärung:
2 * 9
3 * 10
1 * 8
1 * 6

Was mach ich nur falsch *seufz* :cry:

Viele Grüße,
Simon
 
Mit "set -x" zeigt dir die Shell was sie macht.
set +x schaltet dieses "verbose" wieder aus.

Versuch mal eval echo "\${KAUF_${AKT_MONAT}[${ANZ}]}"

Variablen mit index sollten immer mit {} benutzt werden.

Haveaniceday
 
OP
dukenuker

dukenuker

Newbie
Doch noch nicht ganz fertig:

Wie kann ich jetzt abprüfen ob
Code:
${NTX_${AKT_MONAT}[${ANZ}]}
leer ist?

Mit
Code:
if [ -z `eval echo "\${NTX_${AKT_MONAT}[${ANZ}]}"` ]; then
	echo "leer"
fi
bekomme ich "bad substitution".

Und wie kann ich auf alle Elemente des Array zugreifen?

Mit
Code:
for i in ${NTX_${AKT_MONAT}[$@]}; do
	echo $i
done
bekomme ich auch eine Fehler!

Danke & Grüße,
Simon
 
Hi Simon,

For dem if würde ich eine Hilfsvariable+eval nutzen und diese dann im
"if ..." nutzen.

Bei dem for ist zum ersten @ statt $@ notwendig und dann fehlt noch
das indirekte durch eval...

eval "for i in \${NTX_${AKT_MONAT}[@]}; do echo $i ; done"

Haveaniceday
 
Oben