Wie generiere ich eine dynamische Variable in der Art: datei1=test i=1 datei=datei$i # also datei1 Nun hätte ich gerne, dass der Inhalt von datei aber nicht datei1 ist, sondern test. Ich habe nun schon verschiedenste Variationen mit Kommata, Klammern und $ probiert und komme da nicht weiter. Danke für die Hilfe. Gibt es da Unterschiede je nach Shell, speziell sh und bash? Al
Al Bogner
datei1=test i=1 datei=datei$i # also datei1
Nun hätte ich gerne, dass der Inhalt von datei aber nicht datei1 ist, sondern test.
Ich habe nun schon verschiedenste Variationen mit Kommata, Klammern und $ probiert und komme da nicht weiter. Danke für die Hilfe.
Gibt es da Unterschiede je nach Shell, speziell sh und bash?
Das Zauberwort heisst: eval
i=1;x_1=abc;eval x=\${x_${i}}; echo "==> $x"
==> abc und auch:
i=2;eval "x_${i}=123"; echo "==> $x_2" ==> 123
Das sollte für alle Bourne Shells gehen. BTW: die Bash kennt auch Array's, siehe man bash Jürgen -- Dr.rer.nat. Juergen Vollmer, Viktoriastrasse 15, D-76133 Karlsruhe Tel: +49(721) 9204871 Fax: +49(721) 24874 Juergen.Vollmer@[informatik-vollmer.de|alumni.uni-karlsruhe.de|acm.org] www.informatik-vollmer.de
On Thursday 02 October 2003 13:48, Al Bogner wrote:
Wie generiere ich eine dynamische Variable in der Art:
datei1=test i=1 datei=datei$i # also datei1
Nun hätte ich gerne, dass der Inhalt von datei aber nicht datei1 ist, sondern test.
z.B. datei=$(eval echo \$datei$i) oder mit Backticks datei=`eval echo \$datei$i` Andreas
On Thursday 02 October 2003 14:26, Andreas Kyek wrote:
On Thursday 02 October 2003 13:48, Al Bogner wrote:
Wie generiere ich eine dynamische Variable in der Art:
datei1=test i=1 datei=datei$i # also datei1
Nun hätte ich gerne, dass der Inhalt von datei aber nicht datei1 ist, sondern test.
z.B.
datei=$(eval echo \$datei$i) oder mit Backticks datei=`eval echo \$datei$i`
Korrektur: die zweite Variante geht bei mir doch nicht (hatte ich nicht ausprobiert). Warum eigentlich nicht? Ich dachte immer, $(...) und `...` sind äquivalent (OK; Backticks sind die alte Version der sh). Verwirrt Andreas
On Thursday 02 October 2003 14:38, Andreas Kyek wrote:
On Thursday 02 October 2003 14:26, Andreas Kyek wrote:
On Thursday 02 October 2003 13:48, Al Bogner wrote:
Wie generiere ich eine dynamische Variable in der Art:
datei1=test i=1 datei=datei$i # also datei1
Nun hätte ich gerne, dass der Inhalt von datei aber nicht datei1 ist, sondern test.
z.B.
datei=$(eval echo \$datei$i) oder mit Backticks datei=`eval echo \$datei$i`
Korrektur: die zweite Variante geht bei mir doch nicht (hatte ich nicht ausprobiert). Warum eigentlich nicht? Ich dachte immer, $(...) und `...` sind äquivalent (OK; Backticks sind die alte Version der sh).
Verwirrt
Und nochmal ich (ich komme mir vor, als führe ich Selbstgespräche!): Ich habe noch ein bischen weiter geforscht. $(...) und `...` sind NICHT äquivalent. Schaut man sich mal genau an, was die bash da treibt: ------------------------------------------- linux:~> dat=`eval echo \\$datei$i` dat=`eval echo \\$datei$i` eval echo \$datei$i ++ eval echo '$datei1' echo $datei1 +++ echo test + dat=test ------------------------------------------- Die Variante funktioniert also. ------------------------------------------- linux:~> dat=`eval echo \$datei$i` dat=`eval echo \$datei$i` eval echo $datei$i ++ eval echo 1 echo 1 +++ echo 1 + dat=1 ------------------------------------------- Die funktioniert demnach nicht. ------------------------------------------- linux:~> dat=$(eval echo \$datei$i) dat=$(eval echo \$datei$i) eval echo \$datei$i ++ eval echo '$datei1' echo $datei1 +++ echo test + dat=test ------------------------------------------- Die hier funktioniert. Komischerweise braucht die Konstruktion mit $(...) einen Backslash weniger. Kann mir das jemand erklären? Andreas PS: AL, Du hast also zumindest zwei funktionieren Varianten!
Hallo, Am Thu, 02 Oct 2003, Andreas Kyek schrieb: [..]
Und nochmal ich (ich komme mir vor, als führe ich Selbstgespräche!):
Ich habe noch ein bischen weiter geforscht. $(...) und `...` sind NICHT äquivalent. Schaut man sich mal genau an, was die bash da treibt:
------------------------------------------- linux:~> dat=`eval echo \\$datei$i` dat=`eval echo \\$datei$i` eval echo \$datei$i ++ eval echo '$datei1' echo $datei1 +++ echo test + dat=test -------------------------------------------
Die Variante funktioniert also.
Jep. Das \\ kommt _innerhalb_ der `` als ein \ an, und maskiert dann
also innerhalb der `` das $, d.h.:
Vor der ersten Auswertung: dat=`eval echo \\$datei$i`
Nach der ersten Auswertung: dat=`eval echo $datei1`
Nach der 2ten (eval) Ausw.: dat=`echo
------------------------------------------- linux:~> dat=`eval echo \$datei$i` dat=`eval echo \$datei$i` eval echo $datei$i ++ eval echo 1 echo 1 +++ echo 1 + dat=1 -------------------------------------------
Die funktioniert demnach nicht.
Hier faellt das '\' schon mit der ersten Auswertung raus. D.h.: Nach der ersten Auswertung: dat=`eval echo 1` (da $datei leer ist) Nachvollziehen kannst du das, in dem du mal $datei mit einem Wert belegst: $ i=1; datei=DATEI; set -x; dat=`eval echo \$datei$i`; set +x ++ eval echo DATEI1 +++ echo DATEI1 + dat=DATEI1
------------------------------------------- linux:~> dat=$(eval echo \$datei$i) dat=$(eval echo \$datei$i) eval echo \$datei$i ++ eval echo '$datei1' ^ ^ echo $datei1 +++ echo test + dat=test -------------------------------------------
Die hier funktioniert.
Komischerweise braucht die Konstruktion mit $(...) einen Backslash weniger. Kann mir das jemand erklären?
Das liegt daran, wie $() die Argumente uebergibt. Besser ist aber IMO, die Zuweisung mit ins 'eval' zu nehmen, dann faellt die subshell durch `` oder $() weg: $ i=1; datei=DATEI; datei1="foo"; set -x; eval "dat=\"\${datei${i}}\""; set +x + eval 'dat="${datei1}"' ++ dat=foo + set +x Das doppelte quoten ist nicht unbedingt immer noetig. -dnh -- If you don't see why, please stay the fuck away from my code. -- Paul "Rusty" Russel, in /usr/src/linux/Documentation/DocBook/kernel-locking.tmpl
On Thursday 02 October 2003 14:41, Jens Tautenhahn wrote:
Andreas Kyek wrote:
datei=$(eval echo \$datei$i) oder mit Backticks datei=`eval echo \$datei$i`
Hast Du das mal ausprobiert?
Die einzige Möglichkeit ist IMHO wie schon geschrieben:
Wo geschrieben? Wem geschrieben? Wann geschrieben?
datei=${!datei}
linux:~> dat=${!datei} dat=${!datei} + dat= ??? Andreas PS: Das eine meiner Lösungen so nicht geht, hatte ich mittlerweile erwähnt.
Andreas Kyek wrote:
Wo geschrieben? Wem geschrieben? Wann geschrieben?
Oh, da habe ich wohl noch etwas Probleme mit dem neuen Firebird-Build...
datei=${!datei}
linux:~> dat=${!datei} dat=${!datei} + dat=
Meine Zeile war nur zur Ergänzung des Scripts aus der ursprünglichen Frage von Al Bogner. Wenn Du sein Script davorsetzt, sieht das ungefähr so aus: $ cat t.sh #!/bin/sh -x datei1=test i=1 datei=datei$i datei=${!datei} echo $datei $ ./t.sh + datei1=test + i=1 + datei=datei1 + datei=test + echo test test $
PS: Das eine meiner Lösungen so nicht geht, hatte ich mittlerweile erwähnt.
Ja, habe ich mittlerweile gelesen *g* Gruss Jens
Hallo, Am Thu, 02 Oct 2003, Jens Tautenhahn schrieb:
Die einzige Möglichkeit ist IMHO wie schon geschrieben: datei=${!datei}
Awatt. eval dat="\${datei${i}}" -dnh -- "Anybody who really thinks /bin/true should report a version number and a help string (or even a copyright notice) needs to get his head examined." -- Linus Torvalds
Am Donnerstag, 2. Oktober 2003 19:47 schrieb David Haller:
Am Thu, 02 Oct 2003, Jens Tautenhahn schrieb:
Die einzige Möglichkeit ist IMHO wie schon geschrieben: datei=${!datei}
Awatt. eval dat="\${datei${i}}"
Eine hypothetische Frage: Wie denkt ihr, dass es mit der Performance von eval aussieht? Vergleiche dazu: From: Juergen Ilse (juergen@ilse.asys-h.de) Subject: Re: dynamische Variablen Newsgroups: de.comp.os.unix.shell Date: 2001-08-09 08:00:34 PST Al
Hallo, Am Thu, 02 Oct 2003, Al Bogner schrieb:
Am Donnerstag, 2. Oktober 2003 19:47 schrieb David Haller:
Am Thu, 02 Oct 2003, Jens Tautenhahn schrieb:
Die einzige Möglichkeit ist IMHO wie schon geschrieben: datei=${!datei}
Awatt. eval dat="\${datei${i}}"
Eine hypothetische Frage: Wie denkt ihr, dass es mit der Performance von eval aussieht?
'eval' ist ein shell-builtin... Die bash wertet die Zeile einfach zweimal aus und expandiert Variablen etc...
Vergleiche dazu:
From: Juergen Ilse (juergen@ilse.asys-h.de) Subject: Re: dynamische Variablen Newsgroups: de.comp.os.unix.shell Date: 2001-08-09 08:00:34 PST
Bitte bei sowas die Msg-Id angeben, die kann man direkt an google verfuettern (bei Google steht die Msg-Id zwischen selm=... und dem naechsten '&' in der URL. Meintest du diese: http://groups.google.com/groups?\ selm=3b72854a%240%247116%24a5ec1103%40news.ilse.asys-h.de $ ( i=0; time while test $i -lt 10000; do i=$[i+1]; d="`eval echo \"\$datei${i}\"`"; done; ) real 0m21.700s user 0m9.010s sys 0m12.670s $ ( i=0; time while test $i -lt 10000; do i=$[i+1]; eval "d=\"\$datei${i}\""; done; ) real 0m2.669s user 0m2.590s sys 0m0.060s $ ( i=0; time while test $i -lt 10000; do i=$[i+1]; d="datei${i}"; d="${!d}"; done; ) real 0m1.975s user 0m1.930s sys 0m0.020s $ ( i=0; time while test $i -lt 10000; do i=$[i+1]; done; ) real 0m1.029s user 0m1.010s sys 0m0.020s HTH, -dnh -- 13. Perfection (in design) is achieved not when there is nothing more to add, but rather when there is nothing more to take away.'' --- Antoine de Saint-Exupéry as cited in Eric S. Raymond, "The Cathedral and the Bazaar"
Am Donnerstag, 2. Oktober 2003 22:53 schrieb David Haller:
Am Thu, 02 Oct 2003, Al Bogner schrieb:
Am Donnerstag, 2. Oktober 2003 19:47 schrieb David Haller:
Am Thu, 02 Oct 2003, Jens Tautenhahn schrieb:
Bitte bei sowas die Msg-Id angeben, die kann man direkt an google verfuettern (bei Google steht die Msg-Id zwischen selm=... und dem naechsten '&' in der URL. Meintest du diese: http://groups.google.com/groups?\ selm=3b72854a%240%247116%24a5ec1103%40news.ilse.asys-h.de
Ja, bzw. eigentlich den ganzen Thread. Wie bereits gesagt, die Frage ist theoretisch, ich fand die Diskussion dort aber irgendwie interessant. Al
Andreas Kyek schrieb:
On Thursday 02 October 2003 13:48, Al Bogner wrote:
Wie generiere ich eine dynamische Variable in der Art:
datei1=test i=1 datei=datei$i # also datei1
Nun hätte ich gerne, dass der Inhalt von datei aber nicht datei1 ist, sondern test.
z.B.
datei=$(eval echo \$datei$i) oder mit Backticks datei=`eval echo \$datei$i`
So wird das nix :) datei=$(eval echo "\${datei}$i") oder mit Backticks datei=`eval echo "\${datei}$i"` Schönes Beispiel, was passiert wenn man schlampig programmiert ;) so long... bernd
Am Donnerstag, 2. Oktober 2003 22:10 schrieb Bernd Obermayr:
Andreas Kyek schrieb:
On Thursday 02 October 2003 13:48, Al Bogner wrote:
Wie generiere ich eine dynamische Variable in der Art:
datei1=test i=1 datei=datei$i # also datei1
Nun hätte ich gerne, dass der Inhalt von datei aber nicht datei1 ist, sondern test.
z.B.
datei=$(eval echo \$datei$i) oder mit Backticks datei=`eval echo \$datei$i`
So wird das nix :)
Warum? Ich habe in einem Script zB PACKFAKTOR=$(eval echo \$PACKFAKTOR$i) und das funktioniert.
datei=$(eval echo "\${datei}$i") oder mit Backticks datei=`eval echo "\${datei}$i"`
Schönes Beispiel, was passiert wenn man schlampig programmiert ;)
Al
Al Bogner wrote: Warum?
Ich habe in einem Script zB PACKFAKTOR=$(eval echo \$PACKFAKTOR$i) und das funktioniert.
Variable Variablen will man nicht. Why it's stupid to 'use a variable as a variable name' (Eigentlich in Perl, aber weitgehend auch für Shell argumentierbar) http://perl.plover.com/varvarname.html http://perl.plover.com/varvarname2.html http://perl.plover.com/varvarname3.html Man muß sie verwenden, wenn man keine Arrays hat. Man will sie nicht, wenn man Arrays hat. Bash hat Arrays. man bash ... Arrays Bash provides one-dimensional array variables. Any vari able may be used as an array; the declare builtin will explicitly declare an array. There is no maximum limit on the size of an array, nor any requirement that members be indexed or assigned contiguously. Arrays are indexed using integers and are zero-based. An array is created automatically if any variable is assigned to using the syntax name[subscript]=value. The subscript is treated as an arithmetic expression that must evaluate to a number greater than or equal to zero. To explicitly declare an array, use declare -a name (see SHELL BUILTIN COMMANDS below). declare -a name[subscript] is also accepted; the subscript is ignored. Attributes may be specified for an array variable using the declare and readonly builtins. Each attribute applies to all mem bers of an array. Arrays are assigned to using compound assignments of the form name=(value1 ... valuen), where each value is of the form [subscript]=string. Only string is required. If the optional brackets and subscript are supplied, that index is assigned to; otherwise the index of the element assigned is the last index assigned to by the statement plus one. Indexing starts at zero. This syntax is also accepted by the declare builtin. Individual array ele ments may be assigned to using the name[subscript]=value syntax introduced above. Any element of an array may be referenced using ${name[subscript]}. The braces are required to avoid con flicts with pathname expansion. If subscript is @ or *, the word expands to all members of name. These subscripts differ only when the word appears within double quotes. If the word is double-quoted, ${name[*]} expands to a sin gle word with the value of each array member separated by the first character of the IFS special variable, and ${name[@]} expands each element of name to a separate word. When there are no array members, ${name[@]} expands to nothing. This is analogous to the expansion of the special parameters * and @ (see Special Parameters above). ${#name[subscript]} expands to the length of ${name[sub script]}. If subscript is * or @, the expansion is the number of elements in the array. Referencing an array variable without a subscript is equivalent to referencing element zero. The unset builtin is used to destroy arrays. unset name[subscript] destroys the array element at index sub script. unset name, where name is an array, or unset name[subscript], where subscript is * or @, removes the entire array. The declare, local, and readonly builtins each accept a -a option to specify an array. The read builtin accepts a -a option to assign a list of words read from the standard input to an array. The set and declare builtins display array values in a way that allows them to be reused as assignments. Sollten bash-Arrays nicht ausreichen, verwendet man das falsche Werkzeug für den Job -> man perl Kristian
participants (7)
-
Al Bogner
-
Andreas Kyek
-
David Haller
-
Dr. Jürgen Vollmer
-
Illuminatus@t-online.de
-
Jens Tautenhahn
-
Kristian Koehntopp