Discussion:
[bash] Ausgabe von Variablen
Add Reply
Marcel Logen
2025-03-28 18:10:01 UTC
Antworten
Permalink
Wie kann man sich dieses unterschiedliche Verhalten erklären?
(bash)

| ***@o15:/tmp$ ( var=44 ; var2=5 ; { while test $var -lt 49 ; do echo "$((++var)) $((var2++))" ; done ; echo "$var2" ; } ; echo "$var2" )
| 45 5
| 46 6
| 47 7
| 48 8
| 49 9
| 10
| 10

| ***@o15:/tmp$ ( var=44 ; var2=5 ; { echo -e '0\n1\n2\n3\n4' | while read -r ; do echo "$((++var)) $((var2++))" ; done ; echo "$var2" ; } ; echo "$var2" )
| 45 5
| 46 6
| 47 7
| 48 8
| 49 9
| 5
| 5

Ich komme leider irgendwie nicht dahinter.

Marcel
Tim Landscheidt
2025-03-28 18:32:57 UTC
Antworten
Permalink
Post by Marcel Logen
Wie kann man sich dieses unterschiedliche Verhalten erklären?
(bash)
| 45 5
| 46 6
| 47 7
| 48 8
| 49 9
| 10
| 10
| 45 5
| 46 6
| 47 7
| 48 8
| 49 9
| 5
| 5
Ich komme leider irgendwie nicht dahinter.
Das ist beliebter Stolperstein: Jeder Bestandteil einer
Pipeline wird in einer eigenen Subshell ausgeführt
(https://www.gnu.org/software/bash/manual/bash.html#Pipelines):

| […]

| Each command in a multi-command pipeline, where pipes are
| created, is executed in its own subshell, which is a sepa-
| rate process (see Command Execution Environment). If the
| lastpipe option is enabled using the shopt builtin (see The
| Shopt Builtin), the last element of a pipeline may be run by
| the shell process when job control is not active.

| […]

Das heißt, in der ersten Variante gibt es nur eine „Instanz“
der Variablen var und var2, in der zweiten existieren diese
jeweils separat in der Subshell, die durch die äußeren „()“
gestartet wird, dann in der Subshell, die „echo“ ausgeführt,
und zuletzt in der Subshell, die die while-Schleife aus-
führt.

Man kann das normalerweise umgehen, indem man keine Pipe-
lines, sondern beispielsweise process substitutions nutzt:

| $ ( var=44 ; var2=5 ; { while read -r ; do echo "$((++var)) $((var2++))" ; done < <(echo -e '0\n1\n2\n3\n4') ; echo "$var2" ; } ; echo "$var2" )
| 45 5
| 46 6
| 47 7
| 48 8
| 49 9
| 10
| 10
| $

Tim
Marcel Logen
2025-03-28 18:43:54 UTC
Antworten
Permalink
Post by Tim Landscheidt
Post by Marcel Logen
Wie kann man sich dieses unterschiedliche Verhalten erklären?
(bash)
[...]
Post by Tim Landscheidt
Post by Marcel Logen
Ich komme leider irgendwie nicht dahinter.
Das ist beliebter Stolperstein: Jeder Bestandteil einer
Pipeline wird in einer eigenen Subshell ausgeführt
Ah!!!1

Davon hatte ich schon mal was gelesen.

Vielen Dank für den Hinweis.

Marcel (Lines: 25)
--
╭──╮ ╭─────╮ ╭─╮ ╭─╮ ╭─╮ ╭──╮ ╭──╮ ..52..╭───╮ ╭─╮
╯ │ ╰─╮ ╰───╯ ╰────╮ ╭─╯ ╰─╯ ╰───╯ ╰──╯ │ ..49..╭──╯ ╰─────╯ ╰─╮
╰────╯ ╭───╯ │ ╭─────────────────╯ ╭───╯ ..64..╭─╯
╰─────╯ ╰─────────────────────╯ ..64..╰──
Thomas Dorner
2025-03-29 12:06:47 UTC
Antworten
Permalink
Post by Marcel Logen
Post by Tim Landscheidt
Post by Marcel Logen
Wie kann man sich dieses unterschiedliche Verhalten erklären?
(bash)
[...]
Post by Tim Landscheidt
Post by Marcel Logen
Ich komme leider irgendwie nicht dahinter.
Das ist beliebter Stolperstein: Jeder Bestandteil einer
Pipeline wird in einer eigenen Subshell ausgeführt
Davon hatte ich schon mal was gelesen.
Im speziellen Fall (BaSH und Variable im letzten Prozess der Pipe) hilft
auch ein vorher abgesetztes

shopt -s lastpipe

Damit wird für den letzten Teil der Pipe kein extra Prozess gestartet,
sondern er läuft im Hauptprozess.

Viele Grüße, Thomas
--
Adresse gilt nur kurzzeitig!
Ulli Horlacher
2025-03-29 13:23:23 UTC
Antworten
Permalink
Post by Thomas Dorner
Im speziellen Fall (BaSH und Variable im letzten Prozess der Pipe) hilft
auch ein vorher abgesetztes
shopt -s lastpipe
Damit wird für den letzten Teil der Pipe kein extra Prozess gestartet,
sondern er läuft im Hauptprozess.
Was der default bei der ksh ist.
Ich hatte mal einen Kollegen, der die bash als interaktive shell hatte,
seine Skripte aber immer fuer ksh geschrieben hat.
Ich hatte ihn immer gewarnt, dass das keine gute Idee ist.
Antwort:
"Das hab ich schon immer so gemacht!
Ich stell mich vor der Rente nicht mehr um!"

Und prompt tappte er in eine dieser Inkompatibilitaeten und verstand
nicht, warum sich sein Skript so voellig anders verhielt als das, was er
in seiner shell getestet hat.
Fehlermeldungen gabs keine, der Code war ja beides mal korrekt. Nur das
Ergebnis war unterschiedlich. Er hatte VIEL Spass beim Debuggen :-}
--
Ullrich Horlacher Server und Virtualisierung
Rechenzentrum TIK
Universitaet Stuttgart E-Mail: ***@tik.uni-stuttgart.de
Allmandring 30a Tel: ++49-711-68565868
70569 Stuttgart (Germany) WWW: https://www.tik.uni-stuttgart.de/
Christian Weisgerber
2025-03-29 19:10:04 UTC
Antworten
Permalink
Post by Ulli Horlacher
Post by Thomas Dorner
Damit wird für den letzten Teil der Pipe kein extra Prozess gestartet,
sondern er läuft im Hauptprozess.
Was der default bei der ksh ist.
(AT&T ksh sollte man vielleicht sagen. PD ksh und ihre Abkömmlinge
machen das nicht.)

Was die Frage aufwirft, wie das mit Job Control zusammenpasst.
Also ich mache sowas wie

$ cat | read VAR
^Z

Wenn das read in der Shell im Vordergrund ausgeführt wird, dann kann
die sich ja nicht selbst in den Hintergrund legen.

Gerade nochmal mit ksh93 1.0.10 ausprobiert. Ergebnis: Die Shell
hängt und blockiert das TTY, weder ^C (INT) noch ^/ (QUIT) brechen
irgendwas ab. Tja.
https://github.com/ksh93/ksh/issues/750

Nicht ganz durchdacht.
--
Christian "naddy" Weisgerber ***@mips.inka.de
Peter J. Holzer
2025-03-29 20:07:48 UTC
Antworten
Permalink
Post by Christian Weisgerber
Post by Thomas Dorner
Damit wird für den letzten Teil der Pipe kein extra Prozess gestartet,
sondern er läuft im Hauptprozess.
[...]
Post by Christian Weisgerber
Was die Frage aufwirft, wie das mit Job Control zusammenpasst.
Also ich mache sowas wie
$ cat | read VAR
^Z
Wenn das read in der Shell im Vordergrund ausgeführt wird, dann kann
die sich ja nicht selbst in den Hintergrund legen.
Gerade nochmal mit ksh93 1.0.10 ausprobiert. Ergebnis: Die Shell
hängt und blockiert das TTY, weder ^C (INT) noch ^/ (QUIT) brechen
irgendwas ab. Tja.
https://github.com/ksh93/ksh/issues/750
Nicht ganz durchdacht.
Bei der zsh bekommt man die Fehlermeldung:

zsh: job can't be suspended

Abgesehen von der Meldung hat ^Z hier keinen Effekt.

hjp

Christian Weisgerber
2025-03-29 15:25:57 UTC
Antworten
Permalink
Post by Thomas Dorner
Im speziellen Fall (BaSH und Variable im letzten Prozess der Pipe) hilft
auch ein vorher abgesetztes
shopt -s lastpipe
Damit wird für den letzten Teil der Pipe kein extra Prozess gestartet,
sondern er läuft im Hauptprozess.
Achtung, wie in der Anleitung dokumentiert gilt das nur, wenn
gleichzeitig Job Control ausgeschaltet ist.

Standardmäßig ist Job Control bei der Skript-Ausführung ausgeschaltet,
in interaktiven Shells eingeschaltet. Also nicht wundern, wenn's
beim Ausprobieren am Shellprompt nicht funktioniert. Man kann Job
Control mit "set -m" einschalten bzw. "set +m" ausschalten.
--
Christian "naddy" Weisgerber ***@mips.inka.de
Loading...