Discussion:
String Problem
(zu alt für eine Antwort)
Jan Novak
2019-08-27 17:26:05 UTC
Permalink
Hallo,

ich habe einen String der z.B. so aussieht:

1111 222 3333 4444444 jetzt kommt ein langer Text

Die ersten 4 "Wörter" sind zusammenhängend und werden einzeln gebraucht.
Danach folgt ein längerer Text. Der Aufbau des Strings ist immer gleich.

Bisher habe ich mit cut -f[n] -d " " die Wörter 1 -4 gelesen, aber wie
komme ich an den ganzen Satz, der nach dem 4. Leerzeichen folgt und das
in einem Stück?

Mein Wunschergebnis
var1=1111
var2=222
var3=3333
var4=4444444
var5="jetzt kommt ein langer Text"


Jan
Ralf Damaschke
2019-08-27 18:08:40 UTC
Permalink
Post by Jan Novak
1111 222 3333 4444444 jetzt kommt ein langer Text
Mein Wunschergebnis
var1=1111
var2=222
var3=3333
var4=4444444
var5="jetzt kommt ein langer Text"
read var1 var2 var3 var4 var5
Jan Novak
2019-08-27 18:42:12 UTC
Permalink
Post by Ralf Damaschke
Post by Jan Novak
1111 222 3333 4444444 jetzt kommt ein langer Text
Mein Wunschergebnis
var1=1111
var2=222
var3=3333
var4=4444444
var5="jetzt kommt ein langer Text"
read var1 var2 var3 var4 var5
oha... read ... OK... muss ich mal probieren.
Danke.

Jan
Marcel Logen
2019-08-29 20:53:40 UTC
Permalink
Post by Ralf Damaschke
read var1 var2 var3 var4 var5
Mal interessehalber gefragt:

Warum funktioniert das hier nicht (Bash)?

| ***@Microknoppix:~$ echo 1111 22 3333 444 hallow eltz gut sein alssen | read v1 v2 v3 v4
| ***@Microknoppix:~$ echo "$v1"
|
| ***@Microknoppix:~$ echo "$v2"
|
| ***@Microknoppix:~$ echo "$v3"
|
| ***@Microknoppix:~$ echo "$v4"
|
| ***@Microknoppix:~$

"read" sollte laut "man bash" doch von stdin lesen.

So klappt es z. B.:

| ***@Microknoppix:~$ read v1 v2 v3 v4 < <(echo "11111 22 3333 444 555")
| ***@Microknoppix:~$ echo "$v1"
| 11111
| ***@Microknoppix:~$ echo "$v2"
| 22
| ***@Microknoppix:~$ echo "$v3"
| 3333
| ***@Microknoppix:~$ echo "$v4"
| 444 555

Marcel
--
KNOPPIX/8.6
Christian Weisgerber
2019-08-29 21:21:50 UTC
Permalink
Post by Marcel Logen
Warum funktioniert das hier nicht (Bash)?
Das letzte Glied einer Pipe wird in einer Subshell ausgeführt.

Man braucht den Rest der Frage gar nicht mehr zu lesen.
Es ist immer das.
--
Christian "naddy" Weisgerber ***@mips.inka.de
Marcel Logen
2019-08-29 22:56:27 UTC
Permalink
Post by Christian Weisgerber
Post by Marcel Logen
Warum funktioniert das hier nicht (Bash)?
Das letzte Glied einer Pipe wird in einer Subshell ausgeführt.
Danke. Ich habe jetzt mal "shopt -s lastpipe" gemacht.
Damit ging es dann.

Marcel
--
KNOPPIX/8.6
Josef Moellers
2019-08-30 07:09:21 UTC
Permalink
Post by Christian Weisgerber
Post by Marcel Logen
Warum funktioniert das hier nicht (Bash)?
Das letzte Glied einer Pipe wird in einer Subshell ausgeführt.
Nicht nur das:
"Each command in a pipeline is executed as a separate process (i.e., in
a subshell)."
[man bash]

Josef
Marcel Logen
2019-08-30 14:03:19 UTC
Permalink
Post by Josef Moellers
Post by Christian Weisgerber
Das letzte Glied einer Pipe wird in einer Subshell ausgeführt.
"Each command in a pipeline is executed as a separate process (i.e., in
a subshell)."
[man bash]
Da steht auch:

| The standard output of command is connected via a
| pipe to the standard input of command2.

Grübel. Ich habe es noch nicht verstanden.

Warum funktioniert denn beispielsweise das hier?

| ***@Microknoppix:~$ echo 1111 22 333 44444 fuenf sechs sieben acht neun | tr '123' '678'
| 6666 77 888 44444 fuenf sechs sieben acht neun

Liegt es daran, daß "tr" ein externes Kommando ist und
kein Shell-Builtin wie "read"?

Marcel
--
KNOPPIX/8.6
Thomas Noll
2019-08-30 14:17:02 UTC
Permalink
Post by Marcel Logen
Grübel. Ich habe es noch nicht verstanden.
Warum funktioniert denn beispielsweise das hier?
neun | tr '123' '678'
| 6666 77 888 44444 fuenf sechs sieben acht neun
Liegt es daran, daß "tr" ein externes Kommando ist und kein
Shell-Builtin wie "read"?
Das read funktioniert doch auch. In der subshell sind die variablen
belegt.
Marcel Logen
2019-08-30 14:41:00 UTC
Permalink
Post by Thomas Noll
Post by Marcel Logen
Liegt es daran, daß "tr" ein externes Kommando ist und kein
Shell-Builtin wie "read"?
Das read funktioniert doch auch. In der subshell sind die variablen
belegt.
Ah, ja!

| ***@Microknoppix:~$ echo 1 22 333 4444 fuenf sechs sieben acht | (read a1 a2 a3 a4 && echo "$a1" && echo "$a2" && echo "$a3" && echo "$a4")
| 1
| 22
| 333
| 4444 fuenf sechs sieben acht

Danke.

Marcel
--
KNOPPIX/8.6
Josef Moellers
2019-08-30 14:27:32 UTC
Permalink
Post by Marcel Logen
Post by Josef Moellers
Post by Christian Weisgerber
Das letzte Glied einer Pipe wird in einer Subshell ausgeführt.
"Each command in a pipeline is executed as a separate process (i.e., in
a subshell)."
[man bash]
| The standard output of command is connected via a
| pipe to the standard input of command2.
Grübel. Ich habe es noch nicht verstanden.
Was denn?

1) Für jedes Kommando in der Pipeline wird ein neuer Sub-Prozess
erzeugt. Ein "read x" in der Pipeline wird also die Variable "x" (oder
"$x") in der Subshell ändern, nicht aber in der Hauptshell.

2) Im Konstrukt "Kommando1 | Kommando2" ist die "Standardausgabe" von
"Kommando1" mit der Schreibseite einer Pipe und die "Standardeingabe"
von "Kommando2" mit der Leseseite der selben Pipe verbunden. Alles, was
also "Kommando1" in die "Standardausgabe" schreibt, steht kurze Zeit
später an der "Standardeingabe" von "Kommando2" zur Verfügung.
Post by Marcel Logen
Warum funktioniert denn beispielsweise das hier?
| 6666 77 888 44444 fuenf sechs sieben acht neun
Liegt es daran, daß "tr" ein externes Kommando ist und
kein Shell-Builtin wie "read"?
Nein.

1) echo schreibt die 9 "Worte" ("1111" bis "neun") durch Leerzeichen
voneinander getrennt in seine "Standardausgabe"
2) Da die "Standardausgabe" des "echo" über die Pipe mit der
"Standardeingabe" des "tr"-Kommandos verbunden ist, kann "tr" diese 9
Worte lesen und verändern und wiederum in seine "Standardausgabe"
schreiben, die aber immer noch mit dem Terminal verbunden ist.
3) Das ist ubahängig davon, ob "tr" ein Builtin ist oder ein externes
Kommando. Im ersten Fall würde eine Shell das lesen und verarbeiten,
hier liest und verarbeitet "tr" das.

Das "read" *muß* ein Builtin sein, weil es eben den Zustand der Shell
verändern soll, was es als externes Kommando nicht könnte. Da aber in
einer Pipeline jedes Kommando nicht von der Hauptshell sondern von einer
Subshell ausgeführt wird, kann ein "read" in einer Pipeline nicht mal
das! Es verändert den Wert der Variablen in seiner eigenen (Sub-) Shell,
aber nicht in der Haupt-Shell.

HTH,

Josef
Marcel Logen
2019-08-30 17:58:39 UTC
Permalink
Post by Josef Moellers
Post by Marcel Logen
Post by Josef Moellers
Post by Christian Weisgerber
Das letzte Glied einer Pipe wird in einer Subshell ausgeführt.
"Each command in a pipeline is executed as a separate process (i.e., in
a subshell)."
[man bash]
| The standard output of command is connected via a
| pipe to the standard input of command2.
Grübel. Ich habe es noch nicht verstanden.
Was denn?
Daß sich eine Pipeline mit "read" (aus meiner Sicht) anders
verhält als eine Pipeline mit z. B. "tr". Ich hatte angenom-
men, daß die stdout-stdin-Verknüpfung der Pipeline bei "read"
nicht funktionieren würde.

Aber jetzt ist es klar: Die Variablen der Subshell gelten
nur dort, und ich kann sie in der Hauptshell nicht erreichen.
Post by Josef Moellers
1) Für jedes Kommando in der Pipeline wird ein neuer Sub-Prozess
erzeugt. Ein "read x" in der Pipeline wird also die Variable "x" (oder
"$x") in der Subshell ändern, nicht aber in der Hauptshell.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
OK
Post by Josef Moellers
2) Im Konstrukt "Kommando1 | Kommando2" ist die "Standardausgabe" von
"Kommando1" mit der Schreibseite einer Pipe und die "Standardeingabe"
von "Kommando2" mit der Leseseite der selben Pipe verbunden. Alles, was
also "Kommando1" in die "Standardausgabe" schreibt, steht kurze Zeit
später an der "Standardeingabe" von "Kommando2" zur Verfügung.
Das war mir bewußt.

[...]
Post by Josef Moellers
HTH,
Danke für Deine Erläuterungen!

Marcel
--
╭───╮ ╭─╮ ╭──────╮
╭─╯ ╰──╮ │ ╰─╮ ╭──╯ ╭─╯ ╭─╮ ╭─╮
╯ │ ╭──╮ ╭─╯ │ ╰──╮ ╭─╯ ╭──╯ ╰────╮ │ ╰──╮
╰────────╯ ╰───╯ ╰─────╯ ╰────╯ ╰──╯ ╰────────
Christian Weisgerber
2019-08-30 15:19:13 UTC
Permalink
Post by Marcel Logen
Post by Christian Weisgerber
Das letzte Glied einer Pipe wird in einer Subshell ausgeführt.
Grübel. Ich habe es noch nicht verstanden.
Eine Subshell ist ein eigener Kindprozess. Dort gesetzte Variablen
werden nicht an den Elternprozess zurückgeerbt.

$ echo 1111 22 3333 444 hallow eltz gut sein alssen | read v1 v2 v3 v4

read setzt die Variablen in einer Subshell, die gleich darauf wieder
verschwindet...

$ echo "$v1"

... während du hier die Variable im Elternprozess abfrägst.

Man kann eine Subshell explizit mit ( ... ) erzwingen:

$ foo=1
$ (foo=2; echo $foo)
2
$ echo $foo
1
--
Christian "naddy" Weisgerber ***@mips.inka.de
Marcel Logen
2019-08-30 18:04:27 UTC
Permalink
Post by Christian Weisgerber
Post by Marcel Logen
Post by Christian Weisgerber
Das letzte Glied einer Pipe wird in einer Subshell ausgeführt.
Grübel. Ich habe es noch nicht verstanden.
Ich hatte angenommen, die Pipeline würde sich bei "read" und
z. B. "tr" jeweils anders verhalten. Das (von mir) erwartete
Verhalten tritt bei "read" jedoch nicht ein: Für mich sah es
so aus, als wäre die Pipeline bei "read" 'kaputt' und es käme
nichts bei "command2" ("read") an.
Post by Christian Weisgerber
Eine Subshell ist ein eigener Kindprozess. Dort gesetzte Variablen
werden nicht an den Elternprozess zurückgeerbt.
$ echo 1111 22 3333 444 hallow eltz gut sein alssen | read v1 v2 v3 v4
read setzt die Variablen in einer Subshell, die gleich darauf wieder
verschwindet...
^^^^^^^^^^^^
Das war mir nicht klar.
Post by Christian Weisgerber
$ echo "$v1"
... während du hier die Variable im Elternprozess abfrägst.
Ja, so ist es.
Danke!

Marcel
--
╭─╮ ╭─────────╮ ╭─────────╮
╭────╯ ╰────╯ ╰──╮ ╰──────╮ ╰─╮ ╭──╮
──╯ ╭───╯ ╭─╮ ╭─╮ ╭──╮ ╭─╮ ╰─╮ ╰─╯ │
╰─────────╯ ╰─╯ ╰──╯ ╰────╯ ╰────╯ ╰──────
J***@fokus.fraunhofer.de
2019-10-03 06:05:39 UTC
Permalink
Post by Marcel Logen
Warum funktioniert das hier nicht (Bash)?
Das letzte Glied einer Pipe wird in einer Subshell ausgeführt.
Das ist aber nicht bei allen Shells so.

Beim Bourne Shell war es früher so...

Ksh93 und der aktulle Bourne Shell (bosh) erzeugen keinen Subshell, wenn das am
weitesten rechts stehende Programm ein shell Builtin ist.
--
EMail:***@schily.net (home) Jörg Schilling D-13353 Berlin
***@fokus.fraunhofer.de (work) Blog: http://schily.blogspot.com/
URL: http://cdrecord.org/private/ http://sourceforge.net/projects/schilytools/files/
Jan Novak
2019-08-30 05:06:20 UTC
Permalink
Post by Marcel Logen
Post by Ralf Damaschke
read var1 var2 var3 var4 var5
Warum funktioniert das hier nicht (Bash)?
|
|
|
|
"read" sollte laut "man bash" doch von stdin lesen.
| 11111
| 22
| 3333
| 444 555
Genau so ist es auch bei mir.

Jan
Juergen Ilse
2019-09-03 11:44:30 UTC
Permalink
Hallo,
Post by Marcel Logen
Post by Ralf Damaschke
read var1 var2 var3 var4 var5
Warum funktioniert das hier nicht (Bash)?
Es funktioniert, nur werden die Variablen in das Environment einer shell
eingelesen, die danach beendet wird (und deine interaktive shell bekommt
die Variablen nicht von dieser shell "zurueckgegeben" ...).
Post by Marcel Logen
|
|
|
|
"read" sollte laut "man bash" doch von stdin lesen.
Tut es auch, aber das read wird in einer anderen shell ausgefuehrt als
das echo (denn die shell macht an der Stelle kein "multitasking" sondern
jeder Teil der pipe wird in einer separaten shell ausgefuehrt) ...
Post by Marcel Logen
| 11111
| 22
| 3333
| 444 555
Im ersten Fall wird das "read" in eienr subshell ausgefuehrt, die hinterher
wieder beendet wird, in letzterem Fall das "echo". Deswegen hast du die
Variablen in ersterem Fall *nicht* in deienr interaktiven shell, in letzterem
Fall dagegen schon.

Tschuess,
Juergen Ilse (***@usenet-verwaltung.de)
Stefan+ (Stefan Froehlich)
2019-08-27 19:23:10 UTC
Permalink
Post by Jan Novak
Bisher habe ich mit cut -f[n] -d " " die Wörter 1 -4 gelesen, aber wie
komme ich an den ganzen Satz, der nach dem 4. Leerzeichen folgt und das
in einem Stück?
Abgesehen vom schon erwähnten read geht das bei cut mit

cut -f5- -d " "

Servus,
Stefan
--
http://kontaktinser.at/ - die kostenlose Kontaktboerse fuer Oesterreich
Offizieller Erstbesucher(TM) von mmeike

Nur suchen ist harmonischer als lutschen! Stefan: Für die Tage der Wehmut!
(Sloganizer)
Ralph Aichinger
2019-08-27 19:25:15 UTC
Permalink
Post by Stefan+ (Stefan Froehlich)
cut -f5- -d " "
Hm, interessant. Das wird bei mir als invers formatiert ;)
minus-f5-minus mein ich.

/ralph
--
-----------------------------------------------------------------------------
https://aisg.at
ausserirdische sind gesund
Stefan+ (Stefan Froehlich)
2019-08-28 05:35:33 UTC
Permalink
Post by Ralph Aichinger
Post by Stefan+ (Stefan Froehlich)
cut -f5- -d " "
Hm, interessant. Das wird bei mir als invers formatiert ;)
minus-f5-minus mein ich.
Bei mir fett, womit ich vorher auch nicht gerechnet hätte. Eventuell
verhält sich

cut -f 5- -d " "

optisch pflegeleichter?

Servus,
Stefan
--
http://kontaktinser.at/ - die kostenlose Kontaktboerse fuer Oesterreich
Offizieller Erstbesucher(TM) von mmeike

Scheue Rosen ersehnt die Frau: Stefan!
(Sloganizer)
Dennis Preiser
2019-09-07 21:26:34 UTC
Permalink
Post by Stefan+ (Stefan Froehlich)
Post by Ralph Aichinger
Post by Stefan+ (Stefan Froehlich)
cut -f5- -d " "
Hm, interessant. Das wird bei mir als invers formatiert ;)
minus-f5-minus mein ich.
Bei mir fett, womit ich vorher auch nicht gerechnet hätte. Eventuell
verhält sich
cut -f 5- -d " "
optisch pflegeleichter?
Das ist nur das syntax highlighting für Durchgestrichen (stroke im
tinrc). Also sowas: -Text-

Dennis
Stefan+ (Stefan Froehlich)
2019-09-08 07:04:42 UTC
Permalink
Post by Dennis Preiser
Post by Ralph Aichinger
Post by Stefan+ (Stefan Froehlich)
cut -f5- -d " "
Hm, interessant. Das wird bei mir als invers formatiert ;)
minus-f5-minus mein ich.
Eventuell verhält sich
cut -f 5- -d " "
optisch pflegeleichter?
Das ist nur das syntax highlighting für Durchgestrichen (stroke im
tinrc). Also sowas: -Text-
Schon klar, wobei mir davor nur *fett*, _unterstrichen_ und /kursiv/
bekannt waren. Mit dem Folgeposting wollte ich ausprobieren, ob ein
Leerzeichen ausreicht, diese Formatierung zu zerstören: Ja, tut es,
wenigstens beim tin.

Servus,
Stefan
--
http://kontaktinser.at/ - die kostenlose Kontaktboerse fuer Oesterreich
Offizieller Erstbesucher(TM) von mmeike

Toben im grenzenlosen Sein - Stefan, so dumm wie der Schrecken!
(Sloganizer)
Urs Janßen
2019-09-10 12:38:17 UTC
Permalink
Post by Stefan+ (Stefan Froehlich)
bekannt waren. Mit dem Folgeposting wollte ich ausprobieren, ob ein
Leerzeichen ausreicht, diese Formatierung zu zerstören: Ja, tut es,
wenigstens beim tin.
oder verbatim marks drum rum packen

#v+
cut -f5- -d " "
#v-

f'up dcsn
David Seppi
2019-09-08 09:27:40 UTC
Permalink
Post by Stefan+ (Stefan Froehlich)
Bei mir fett, womit ich vorher auch nicht gerechnet hätte. Eventuell
verhält sich
cut -f 5- -d " "
optisch pflegeleichter?
#v+

cut -f5- -d " "

#v-

... hilft bei mir.
--
David Seppi
1220 Wien
Juergen Ilse
2019-09-03 11:37:49 UTC
Permalink
Hallo,
Post by Jan Novak
1111 222 3333 4444444 jetzt kommt ein langer Text
Die ersten 4 "Wörter" sind zusammenhängend und werden einzeln gebraucht.
Danach folgt ein längerer Text. Der Aufbau des Strings ist immer gleich.
Bisher habe ich mit cut -f[n] -d " " die Wörter 1 -4 gelesen, aber wie
komme ich an den ganzen Satz, der nach dem 4. Leerzeichen folgt und das
in einem Stück?
Mein Wunschergebnis
var1=1111
var2=222
var3=3333
var4=4444444
var5="jetzt kommt ein langer Text"
Wie waere es, die Zeile einfach mit "read -r" von der shell einlesen zu
lassen (ggfs. mit passend gesetztem IFS, wenn nur Leerzeichen und nicht
beliebiger whitespace als Trenner zwischen den Feldern akzeptiert werden
sollen):

IFS=" " read -r var1 var2 var3 var4 var5

var5 enthaelt dann den Rest der Zeile der noch uebrig ist, wenn var1
bis var4 gelesen wurden (und die Option "-r" dient dazu, dass ein "\"
ggfs. woertlich gelesen und nicht alss "quoting" interpretiert wird) ...

Tschues,
Juergen Ilse (***@usenet-verwaltung.de)
Loading...