![](https://seccdn.libravatar.org/avatar/e832594709d2f3e981e8ad5c26c52588.jpg?s=120&d=mm&r=g)
Hallo *, ich habe da nochmal ein Problem mit Variablen unter der bash, d. h. eher mit den subshells und der Übergabe der Variablen. Folgende Konstruktion: $x=42 while read resultat do if [ $resultat -lt $x ] then x=$resultat ... fi done </var/log/foo.stats echo $x Der if-Teil wird wie geplant abgearbeitet, innerhalb des while ... done funktioniert die Zuweisung zu x auch. Aber nach dem done ist x wieder 42. Ich nehme mal an, dass die Schleife in einer subshell abgearbeitet wird und die variable nicht an die Vatershell übergeben wird. Wie kann ich das denn unterbinden. Und gibt es eine Regel, wann die bash subshells aufmacht und wann nicht? Martin ps: Ich habe derzeit ein kleines Problem mit man bash: mb 18283 0.0 0.0 1616 360 ? D 10:42 0:00 /usr/bin/gzip -dc /var/cache/man/cat1/bashbuiltins.1.gz Prozess ist D und man bash bleibt stehen. Reboot ist keine Option, habe hier eine mehrtägige statistische Berechnung am laufen, die ich nicht abbrechen kann. :( Ich bitte um Nachsicht mit RTFMs. -- when in danger or in doubt, run in circles, scream and shout! pgp-key: via wwwkeys.de.pgp.net, key id is 0x21eec9b0
![](https://seccdn.libravatar.org/avatar/735ea797d876adb026ae955e8adbf597.jpg?s=120&d=mm&r=g)
On Sam, 23 Nov 2002 at 12:06 (+0100), Martin Borchert wrote:
Hallo *,
ich habe da nochmal ein Problem mit Variablen unter der bash, d. h. eher mit den subshells und der Übergabe der Variablen. Folgende Konstruktion:
$x=42 ^ Typo? Das muss x=42 heissen (ohne $ bei Zuweisungen) while read resultat do if [ $resultat -lt $x ] then x=$resultat ... fi done </var/log/foo.stats echo $x
Mit der o. g. Korrektur funktioniert das hier bestens. Ohne Korrektur hagelt es logischerweise Fehlermeldungen. Eine Subshell wird nur bei Pipes aufgemacht, also bei Konstrukten der Form: cat /var/log/foo.stats | while read resultat; do ... done Jan
![](https://seccdn.libravatar.org/avatar/208f884b860bee2b1a5f890e5c5756d7.jpg?s=120&d=mm&r=g)
Jan Trippler wrote:
On Sam, 23 Nov 2002 at 12:06 (+0100), Martin Borchert wrote: [...] Mit der o. g. Korrektur funktioniert das hier bestens. Ohne Korrektur hagelt es logischerweise Fehlermeldungen. Eine Subshell wird nur bei Pipes aufgemacht, also bei Konstrukten der Form: cat /var/log/foo.stats | while read resultat; do ... done
Das "nur" stimmt nicht ganz :-) Siehe dazu z.B. http://marc.theaimsgroup.com/?l=suse-linux&m=102855127512194&w=2 Gruesse, Thomson -- Thomas Hertweck, Dipl.-Geophys. Geophysikalisches Institut, Universitaet Karlsruhe (TH)
![](https://seccdn.libravatar.org/avatar/e832594709d2f3e981e8ad5c26c52588.jpg?s=120&d=mm&r=g)
Am Samstag, 23. November 2002 17:51:17 schrieb Jan Trippler:
On Sam, 23 Nov 2002 at 12:06 (+0100), Martin Borchert wrote:
Hallo *, ich habe da nochmal ein Problem mit Variablen unter der bash, d. h. eher mit den subshells und der Übergabe der Variablen. Folgende Konstruktion: $x=42 ^ Typo? Das muss x=42 heissen (ohne $ bei Zuweisungen)
Stimmt. Das kommt davon, wenn man kein Copy&Paste macht.
while read resultat do if [ $resultat -lt $x ] then x=$resultat ... fi done </var/log/foo.stats echo $x Mit der o. g. Korrektur funktioniert das hier bestens. Ohne Korrektur hagelt es logischerweise Fehlermeldungen.
Wunderlich. Jetzt geht's hier auch. Das Problem war aber sicher nicht das $x=..., das stand nicht in dem Skript drin. Und es wurde ja auch ohne Fehlermeldung ausgeführt.
Eine Subshell wird nur bei Pipes aufgemacht, also bei Konstrukten der Form: cat /var/log/foo.stats | while read resultat; do ... done
Ok, das kann ich mir merken. Nächste Frage, rein interessehalber: Muss ich den Umweg über eine Datei machen oder kann ich die Ausgabe eines Befehls irgendwie "von hinten" in eine Schleife pipen? while read foo; do echo $bar; done<`ls *` funktioniert nicht. Und ja, ich weiß, es ist ein blödes Beispiel. Martin -- when in danger or in doubt, run in circles, scream and shout! pgp-key: via wwwkeys.de.pgp.net, key id is 0x21eec9b0
![](https://seccdn.libravatar.org/avatar/cafdf3e357250f82df446ad37e96d2d8.jpg?s=120&d=mm&r=g)
* On Sat, 23 Nov 2002 at 18:29 +0100, Martin Borchert wrote: [...]
Ok, das kann ich mir merken. Nächste Frage, rein interessehalber: Muss ich den Umweg über eine Datei machen oder kann ich die Ausgabe eines Befehls irgendwie "von hinten" in eine Schleife pipen? while read foo; do echo $bar; done<`ls *` funktioniert nicht. Und ja, ich weiß, es ist ein blödes Beispiel.
Warum gerade von hinten pipen? ls * | while read foo; do echo $bar; done -- Adalbert GPG welcome, request public key: mailto:adalbert+key@lopez.at
![](https://seccdn.libravatar.org/avatar/e832594709d2f3e981e8ad5c26c52588.jpg?s=120&d=mm&r=g)
Am Samstag, 23. November 2002 18:38:18 schrieb Adalbert Michelic:
* On Sat, 23 Nov 2002 at 18:29 +0100, Martin Borchert wrote:
Ok, das kann ich mir merken. Nächste Frage, rein interessehalber: Muss ich den Umweg über eine Datei machen oder kann ich die Ausgabe eines Befehls irgendwie "von hinten" in eine Schleife pipen? while read foo; do echo $bar; done<`ls *` funktioniert nicht. Und ja, ich weiß, es ist ein blödes Beispiel. Warum gerade von hinten pipen? ls * | while read foo; do echo $bar; done
Weil ich, wenn ich das |-Konstrukt benutze, nach dem done nicht auf Veränderungen von Variablen zugreifen kann, die innerhalb der Schleife durchgeführt werden. Deswegen ja die Lösung mit while read; do ... done<foo. Ohne pipe. Oder steh ich jetzt völlig auf dem Schlauch? Martin -- when in danger or in doubt, run in circles, scream and shout! pgp-key: via wwwkeys.de.pgp.net, key id is 0x21eec9b0
![](https://seccdn.libravatar.org/avatar/c65f0a9d70486d425ffd4799ddb379fc.jpg?s=120&d=mm&r=g)
* Martin Borchert schrieb am 23.Nov.2002:
Weil ich, wenn ich das |-Konstrukt benutze, nach dem done nicht auf Veränderungen von Variablen zugreifen kann, die innerhalb der Schleife durchgeführt werden. Deswegen ja die Lösung mit while read; do ... done<foo. Ohne pipe. Oder steh ich jetzt völlig auf dem Schlauch?
Ja. Wie immer die Synax auch lauten mag, wie soll die shell eine Pipe ausführen, ohne einen neuen Prozeß aufzumachen. Und Variablen, die im Kindprozeß verändert werden, kann der Elterprozeß nicht lesen. Wenn Du das ganze Skript hinter einer Pipe hängst, geht es wieder. Bernd -- Alle meine Signaturen sind rein zufällig und haben nichts mit dem Text oder dem Schreiber zu tun, dem ich antworte. Falls irgendwelche Unrichtigkeiten dabei sein sollten, so bedauere ich das. Es wäre nett, wenn Du mich benachrichtigen würdest. |Zufallssignatur 0
![](https://seccdn.libravatar.org/avatar/735ea797d876adb026ae955e8adbf597.jpg?s=120&d=mm&r=g)
On Sam, 23 Nov 2002 at 18:38 (+0100), Adalbert Michelic wrote:
* On Sat, 23 Nov 2002 at 18:29 +0100, Martin Borchert wrote: [...]
Ok, das kann ich mir merken. Nächste Frage, rein interessehalber: Muss ich den Umweg über eine Datei machen oder kann ich die Ausgabe eines Befehls irgendwie "von hinten" in eine Schleife pipen? while read foo; do echo $bar; done<`ls *` funktioniert nicht. Und ja, ich weiß, es ist ein blödes Beispiel.
Warum gerade von hinten pipen?
ls * | while read foo; do echo $bar; done
und genau dann haben wir das Problem mit der Subshell (da hatten wir vor einigen Wochen mal einen ausführlichen Thread drüber). Die Änderungen an $bar innerhalb der Schleife kommen dann nicht mehr im Kontext außerhalb dieser Schleife an: jan@k500:~/tmp> cat foo.stats 44 41 jan@k500:~/tmp> x=42 jan@k500:~/tmp> cat foo.stats | while read y; do
test $y -lt $x && x=$y done jan@k500:~/tmp> echo $x 42
Bei einfachen Ausgaben wie dem Minimum im ursprünglichen Script funktioniert z. B. folgendes Konstrukt: x=`cat foo.stats | awk ' BEGIN { x = 42 } { if ($1 < x) x = $1 } END { print x } '` Jan
![](https://seccdn.libravatar.org/avatar/440955ab796fb403fba608d0df23b654.jpg?s=120&d=mm&r=g)
Hallo Martin, hallo Leute, Am Samstag, 23. November 2002 12:06 schrieb Martin Borchert:
ich habe da nochmal ein Problem mit Variablen unter der bash, d. h. eher mit den subshells und der Übergabe der Variablen. Folgende Konstruktion:
$x=42 ^ Lass das $-Zeichen weg, dann funktioniert es ;-)
Also: x=42
while read resultat do if [ $resultat -lt $x ] then x=$resultat ... fi done </var/log/foo.stats echo $x
Du suchst also nach der kleinsten Zahl in der Datei... Achtung Fallstrick: Wenn in der Datei nur Zahlen > 42 stehen, werden die ignoriert, da x von Anfang an nicht höher steht. Ist das so gewollt? Beispiel: ----- foo.stats ----- 120 2489 430 60 ----- Ende foo.stats ----- Dein Script einmal ausführen, Ergebnis: cb@tux~> echo $x 42 # !!! Die kleinste Zahl in der Datei ist aber 60!
Der if-Teil wird wie geplant abgearbeitet, innerhalb des while ... done funktioniert die Zuweisung zu x auch.
Sicher?
Ich nehme mal an, dass die Schleife in einer subshell abgearbeitet wird und die variable nicht an die Vatershell übergeben wird. Wie kann ich das denn unterbinden. Und gibt es eine Regel, wann die bash subshells aufmacht und wann nicht?
In diesem Fall gibt es wohl keine Subshell. Subshells werden AFAIK aufgemacht - bei Verwendung von Pipes - _innerhalb_ von Backticks - bei Verwendung von ( ... ) - also gezieltem Öffnen einer Subshell - aber _NICHT_ bei Gruppierung von Befehlen mit { ... }
ps: Ich habe derzeit ein kleines Problem mit man bash: mb 18283 0.0 0.0 1616 360 ? D 10:42 0:00 /usr/bin/gzip -dc /var/cache/man/cat1/bashbuiltins.1.gz
Prozess ist D und man bash bleibt stehen. Reboot ist keine Option, habe hier eine mehrtägige statistische Berechnung am laufen, die ich nicht abbrechen kann. :( Ich bitte um Nachsicht mit RTFMs.
http://www.google.com/search?q=man%20bash *SCNR* Gruß Christian Boltz -- soviel zu Win. Was hat Dich denn da geritten? Auf Win- Fehlermeldungen würde ich nix geben. Wenn das OS konsequent wäre, würde es sich selbst löschen. [Philipp Zacharias in suse-linux]
participants (6)
-
Adalbert Michelic
-
B.Brodesser@t-online.de
-
Christian Boltz
-
Jan.Trippler@t-online.de
-
Martin Borchert
-
Thomas Hertweck