bash array while read
Hallo Liste, warum funktioniert folgendes Skript nicht: i=1 /usr/bin/cinternet -I | while read LINE; DSL[i++]=$LINE; done mit: basar:/etc/ppp # cinternet -I 01 i dsl1 02 a dsl2 Ergebnis: basar:/etc/ppp #echo ${DSL[1]} basar:/etc/ppp #echo ${DSL[2]} Viele Grüße Günter -- Guenter Ohmer Jahnstrasse 24 D 76865 Rohrbach mailto:guenter.ohmer@gmx.de -- Um die Liste abzubestellen, schicken Sie eine Mail an: opensuse-de+unsubscribe@opensuse.org Um eine Liste aller verfuegbaren Kommandos zu bekommen, schicken Sie eine Mail an: opensuse-de+help@opensuse.org
Am Donnerstag, 14. August 2008 09:40:34 schrieb Günter Ohmer:
Hallo Liste,
warum funktioniert folgendes Skript nicht:
i=1 /usr/bin/cinternet -I | while read LINE; DSL[i++]=$LINE; done
mit: basar:/etc/ppp # cinternet -I 01 i dsl1 02 a dsl2
Ergebnis: basar:/etc/ppp #echo ${DSL[1]}
basar:/etc/ppp #echo ${DSL[2]}
1. Weil syntaktisch falsch while read LINE; do DSL[$((i++))]=$LINE; done; 2. man bash: Each command in a pipeline is executed as a separate process (i.e., in a subshell). Probier mal (hier wird keine Pipe benutzt) i=1; while read LINE; do echo $((i++)); done < EINE_DATEI ; echo danach i = $i; Hier wird danach der "erwartete" Wert ausgegeben. Lösung also: TF=/tmp/foo.$$ /usr/bin/cinternet -I > $TF while read LINE; do DSL[$((i++))]=$LINE; done < $TF Bye Jürgen -- Dr.rer.nat. Juergen Vollmer, Viktoriastrasse 15, D-76133 Karlsruhe Tel: +49(721) 92 04 87 1 Fax: +49(721) 92 04 87 2 Juergen.Vollmer@informatik-vollmer.de www.informatik-vollmer.de Internet-Telefonie: www.skype.com Benutzer: juergen.vollmer
Hallo Jürgen, Am Donnerstag, 14. August 2008 09:59:55 schrieb Dr. Jürgen Vollmer:
1. Weil syntaktisch falsch while read LINE; do DSL[$((i++))]=$LINE; done;
while read LINE; do DSL[i++]=$LINE; done war schon richtig: man bash: The subscript is treated as an arithmetic expression that must evaluate to a number greater than or equal to zero. ... ... Shell variables are allowed as operands; parameter expansion is performed before the expression is evaluated.
2. man bash: Each command in a pipeline is executed as a separate process (i.e., in a subshell).
Probier mal (hier wird keine Pipe benutzt) i=1; while read LINE; do echo $((i++)); done < EINE_DATEI ; echo danach i = $i;
Hier wird danach der "erwartete" Wert ausgegeben.
Der Umweg über die Datei war mir schon bekannt, aber read liest auch von der Standard-Eingabe man read: (bash buildin commands) read [-ers] [-u fd] [-t timeout] [-a aname] [-p prompt] [-n nchars] [-d delim] [name ...] One line is read from the standard input, or from the file descriptor fd supplied as an argument to the -u option, and the first word
Lösung also: TF=/tmp/foo.$$ /usr/bin/cinternet -I > $TF while read LINE; do DSL[$((i++))]=$LINE; done < $TF
nach ein bisschen googlen (oder googeln?) sieht meine Lösung jetzt so aus: basar:/etc/ppp # unset DSL; i=1; while read LINE; do DSL[i]=$LINE; echo "$i ${DSL[i++]}"; done < <(/usr/bin/cinternet -I); 1 01 i dsl1 2 02 a dsl2 Vielen Dank für die Unterstützung und viele Grüße Günter -- Guenter Ohmer Jahnstrasse 24 D 76865 Rohrbach mailto:guenter.ohmer@gmx.de -- Um die Liste abzubestellen, schicken Sie eine Mail an: opensuse-de+unsubscribe@opensuse.org Um eine Liste aller verfuegbaren Kommandos zu bekommen, schicken Sie eine Mail an: opensuse-de+help@opensuse.org
Am Donnerstag, 14. August 2008 15:26:06 schrieb Günter Ohmer:
Am Donnerstag, 14. August 2008 09:59:55 schrieb Dr. Jürgen Vollmer:
1. Weil syntaktisch falsch while read LINE; do DSL[$((i++))]=$LINE; done;
while read LINE; do DSL[i++]=$LINE; done
war schon richtig:
ok, im ursprünglichen Posting fehlte das "do" nach der While-Bedingung, da kam die Fehlermeldung i=1; /usr/bin/cinternet -I | while read LINE; DSL[i++]=$LINE; done bash: syntax error near unexpected token `done' her. Das hatte ich übersehen.
man bash: The subscript is treated as an arithmetic expression that must evaluate to a number greater than or equal to zero. ... ... Shell variables are allowed as operands; parameter expansion is performed before the expression is evaluated.
aber man lernt ja nie aus
basar:/etc/ppp # unset DSL; i=1; while read LINE; do DSL[i]=$LINE; echo "$i ${DSL[i++]}"; done < <(/usr/bin/cinternet -I); 1 01 i dsl1
<(/usr/bin/cinternet -I) Dinge gibt's, ........ Bye Jürgen -- Dr.rer.nat. Juergen Vollmer, Viktoriastrasse 15, D-76133 Karlsruhe Tel: +49(721) 92 04 87 1 Fax: +49(721) 92 04 87 2 Juergen.Vollmer@informatik-vollmer.de www.informatik-vollmer.de Internet-Telefonie: www.skype.com Benutzer: juergen.vollmer
Hallo, Am Don, 14 Aug 2008, =?iso-8859-1?q?Dr. J=FCrgen Vollmer?= schrieb:
basar:/etc/ppp # unset DSL; i=1; while read LINE; do DSL[i]=$LINE; echo "$i ${DSL[i++]}"; done < <(/usr/bin/cinternet -I); 1 01 i dsl1 ^^^ Das funktioniert aber nur mit aktuellen Bashes.
<(/usr/bin/cinternet -I)
Dinge gibt's, ........
Nennt sich "process substitution" und ist ein ziemlich cooles Feature der Bash ;) Siehe: man -P"less '+/^ *process substitution'" bash Und man sollte die Variablen quoten (wie immer: quoten so gut es geht), und was auch mit meiner angestaubten bash-2.03 tut: i=1; while read LINE; do DSL[i]="$LINE"; echo "$i ${DSL[ i += 1 ]}"; done < <(/usr/bin/cinternet -I); Aber andererseits halte ich meine Lösung ganz ohne while+read für eleganter ;) Have fun, -dnh -- und *echte* Männer benutzen Linux -- wegen der langen Kommandozeilen ("Meine ist länger als deine!"). Dann muss man nicht mehr Krieg spielen, um zu zeigen, wie hart man ist. -- S. Lauterkorn -- Um die Liste abzubestellen, schicken Sie eine Mail an: opensuse-de+unsubscribe@opensuse.org Um eine Liste aller verfuegbaren Kommandos zu bekommen, schicken Sie eine Mail an: opensuse-de+help@opensuse.org
Hallo, Am Don, 14 Aug 2008, =?iso-8859-1?q?Dr. J=FCrgen Vollmer?= schrieb:
Lösung also: TF=/tmp/foo.$$
*patsch* man mktemp
/usr/bin/cinternet -I > $TF while read LINE; do DSL[$((i++))]=$LINE; done < $TF
oIFS="$IFS" IFS=" " DSL=( $( /usr/bin/cinternet -I ) ) for i in "${DSL[@]}"; do echo "»$i«" done HTH, -dnh -- panic("ocfs2 is very sorry to be fencing this system by panicing\n"); -- /usr/src/linux/fs/ocfs2/cluster/quorum.c -- Um die Liste abzubestellen, schicken Sie eine Mail an: opensuse-de+unsubscribe@opensuse.org Um eine Liste aller verfuegbaren Kommandos zu bekommen, schicken Sie eine Mail an: opensuse-de+help@opensuse.org
Am Donnerstag, 14. August 2008 21:46:06 schrieb David Haller:
Hallo,
Am Don, 14 Aug 2008, =?iso-8859-1?q?Dr. J=FCrgen Vollmer?= schrieb:
Lösung also: TF=/tmp/foo.$$
*patsch* man mktemp
aua Bye Jürgen -- Dr.rer.nat. Juergen Vollmer, Viktoriastrasse 15, D-76133 Karlsruhe Tel: +49(721) 92 04 87 1 Fax: +49(721) 92 04 87 2 Juergen.Vollmer@informatik-vollmer.de www.informatik-vollmer.de Internet-Telefonie: www.skype.com Benutzer: juergen.vollmer
Hallo, Am Don, 14 Aug 2008, =?iso-8859-1?q?Dr. J=FCrgen Vollmer?= schrieb:
Am Donnerstag, 14. August 2008 21:46:06 schrieb David Haller:
Hallo,
Am Don, 14 Aug 2008, =?iso-8859-1?q?Dr. J=FCrgen Vollmer?= schrieb:
Lösung also: TF=/tmp/foo.$$
*patsch* man mktemp
aua
*Eisbeutel + Stück Schoki reich* Ja, ich geb's zu, ich berücksichtige das auch nicht immer, aber Temp-Dateien sollten keine erratbaren Namen haben (und die PID ist vorhersagbar). Wenn nicht mktemp, dann sollte man einen festen Dateinamen in /var/run/ oder /var/state/ oder so verwenden, und dort natürlich passende, d.h. minimale, Rechte setzen. Achso, bei meinem Vorschlag fehlt noch das IFS="$oIFS" nach dem LINES=... *gähn*, -dnh -- Wer im Sinne schwach ist, der kann nicht anders. Er muss Schwachsinn produzieren. [Woko° in dag°] -- Um die Liste abzubestellen, schicken Sie eine Mail an: opensuse-de+unsubscribe@opensuse.org Um eine Liste aller verfuegbaren Kommandos zu bekommen, schicken Sie eine Mail an: opensuse-de+help@opensuse.org
participants (3)
-
David Haller
-
Dr. Jürgen Vollmer
-
Günter Ohmer