(erledigt) Bash: Textstring in einzelne Buchstaben/Charaktere zerlegen

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
ren22

(erledigt) Bash: Textstring in einzelne Buchstaben/Charaktere zerlegen

Beitrag von ren22 » 19.02.2018 15:35:49

Hallo,

ich versuche gerade ein String "hallo - welt" in einzelne Buchstaben zu zerlegen, leider scheitert es an der Ausgabe bei Leerfeldern.

Code: Alles auswählen

string="hallo - welt"

for i in $( echo $string| grep -o .); do
    echo "akueller Buchstabe ist: $i"
done
Ausgabe:

Code: Alles auswählen

akueller Buchstabe ist: h
akueller Buchstabe ist: a
akueller Buchstabe ist: l
akueller Buchstabe ist: l
akueller Buchstabe ist: o
akueller Buchstabe ist: -
akueller Buchstabe ist: w
akueller Buchstabe ist: e
akueller Buchstabe ist: l
akueller Buchstabe ist: t
warum werden leerfelder nicht ausgeben?
Zuletzt geändert von ren22 am 19.02.2018 16:28:50, insgesamt 2-mal geändert.

Benutzeravatar
MSfree
Beiträge: 10686
Registriert: 25.09.2007 19:59:30

Re: Bash: Textstring in einzelne Buchstaben/Chraktere zerlegen

Beitrag von MSfree » 19.02.2018 16:03:28

Very quick and very dirty

Code: Alles auswählen

#!/bin/bash

string="hallo - welt"
number=0
letter=${string:$number:1}

until test -z "$letter"
do
  echo $letter
  number=$number+1
  letter=${string:$number:1}
done

uname
Beiträge: 12046
Registriert: 03.06.2008 09:33:02

Re: Bash: Textstring in einzelne Buchstaben/Chraktere zerlegen

Beitrag von uname » 19.02.2018 16:04:57

Vielleicht so:

Code: Alles auswählen

string="hallo - welt";for i in $(seq 1 ${#string});do echo "akueller Buchstabe ist:" ${string:var=$((i-1)):1};done
Oder besser mit awk:

Code: Alles auswählen

string="hallo - welt";echo $string | awk 'BEGIN{FS=""}{for(i=1;i<=NF;i++)print "akueller Buchstabe ist: "$(i)}'
ren22 hat geschrieben:warum werden leerfelder nicht ausgeben?
Weil "echo $string" den String in drei Stücke zerlegt und die Leerzeichen entfernt.

Benutzeravatar
hikaru
Moderator
Beiträge: 13559
Registriert: 09.04.2008 12:48:59

Re: Bash: Textstring in einzelne Buchstaben/Chraktere zerlegen

Beitrag von hikaru » 19.02.2018 16:27:06

uname hat geschrieben: ↑ zum Beitrag ↑
19.02.2018 16:04:57
ren22 hat geschrieben:warum werden leerfelder nicht ausgeben?
Weil "echo $string" den String in drei Stücke zerlegt und die Leerzeichen entfernt.
Jein. Wenn echo hier der Übeltäter wäre, dann würde es ausreichen, $string zu quoten damit wirklich die gesamte Zeile als ein String behandelt wird: echo "$string"
Genau genommen zerlegt nicht echo den String, sondern die for-Schleife, denn Leerzeichen (Whitespaces?) sind standardmäßig die "internal field seperators" (IFS) in bash.

Der ursprüngliche Code funktioniert daher, wenn man einfach den IFS neu definiert:

Code: Alles auswählen

IFS=$'\n'

string="hallo - welt"

for i in $( echo $string| grep -o .); do
    echo "akueller Buchstabe ist: $i"
done

ren22

Re: Bash: Textstring in einzelne Buchstaben/Chraktere zerlegen

Beitrag von ren22 » 19.02.2018 16:28:13

Danke schön an alle beteiligten. Wieder was gelernt. :THX: :THX: :THX: :THX:

ren22

Re: (erledigt) Bash: Textstring in einzelne Buchstaben/Charaktere zerlegen

Beitrag von ren22 » 19.02.2018 16:38:40

wenn ich den/die "IFS" "internal field seperators" vor der for Schleife schreibe
und noch weiteren code in dem bashscript habe, greift dann IFS auch auf den rest des codes zu ? und wenn ja wie beendet man das IFS wieder nach der for schleife, damit keine Fehler im rest des Codes auftreten.

Benutzeravatar
hikaru
Moderator
Beiträge: 13559
Registriert: 09.04.2008 12:48:59

Re: (erledigt) Bash: Textstring in einzelne Buchstaben/Charaktere zerlegen

Beitrag von hikaru » 19.02.2018 16:50:37

Der geänderte IFS gilt ab dem Punkt der Änderung für die gesamte Shell (in dem Fall also für das komplette Script).
Falls du später im Code wieder den Standard-IFS haben willst, dann kannst du ihn auch wieder zurücksetzen:

Code: Alles auswählen

unset IFS
Das ist zwar wenig Schreibarbeit, aber es erscheint mir konzeptuell unschön, eigentlich als Umgebungsvariablen gedachte Schalter in einem Script mehrfach an- und auszuknipsen, damit der Code läuft. In dem Fall würde ich dann doch eine andere Lösung bevorzugen.

ren22

Re: (erledigt) Bash: Textstring in einzelne Buchstaben/Charaktere zerlegen

Beitrag von ren22 » 19.02.2018 16:54:24

Code: Alles auswählen

IFS=$'\n'
string="hallo - welt"
for i in $( echo $string| grep -o .); do
    echo "akueller Buchstabe ist: $i"
done
unset IFS
also, sollte dann der rest in dem script von den obrigen Zeilen nicht beeinflusst werden ?

tobo
Beiträge: 1964
Registriert: 10.12.2008 10:51:41

Re: (erledigt) Bash: Textstring in einzelne Buchstaben/Charaktere zerlegen

Beitrag von tobo » 19.02.2018 17:17:33

Doch, bei einem unset ist die Variable weg. Entweder speicherst du dir den IFS und setzt ihn danach wieder auf den alten Wert:

Code: Alles auswählen

OLD_IFS="$IFS"
IFS=$`\n'
...
IFS="$OLD_IFS"
oder lässt das alles unberührt und quotest die For-Schleife:

Code: Alles auswählen

for i in "$( echo $string| grep -o .)"; do

uname
Beiträge: 12046
Registriert: 03.06.2008 09:33:02

Re: (erledigt) Bash: Textstring in einzelne Buchstaben/Charaktere zerlegen

Beitrag von uname » 19.02.2018 19:46:21

Danke. Auch wieder was gelernt.

Benutzeravatar
hikaru
Moderator
Beiträge: 13559
Registriert: 09.04.2008 12:48:59

Re: (erledigt) Bash: Textstring in einzelne Buchstaben/Charaktere zerlegen

Beitrag von hikaru » 19.02.2018 21:08:03

tobo hat geschrieben: ↑ zum Beitrag ↑
19.02.2018 17:17:33
oder lässt das alles unberührt und quotest die For-Schleife:

Code: Alles auswählen

for i in "$( echo $string| grep -o .)"; do
Ich verstehe noch nicht ganz was hier passiert, aber offenbar wird die Schleife nur einmal durchlaufen, gibt in diesem einen Durchlauf aber trotzdem alle Buchstaben aus. Das wird deutlich, wenn man wie ren22 einen fixen String mit ausgibt:

Code: Alles auswählen

string="hallo - welt"

for i in "$( echo $string| grep -o .)"; do
            echo "akueller Buchstabe ist: $i"
done
erzeugt:

Code: Alles auswählen

$ bash test.sh 
akueller Buchstabe ist: h
a
l
l
o
 
-
 
w
e
l
t

RobertDebiannutzer
Beiträge: 385
Registriert: 16.06.2017 09:52:36

Re: (erledigt) Bash: Textstring in einzelne Buchstaben/Charaktere zerlegen

Beitrag von RobertDebiannutzer » 19.02.2018 21:45:23

Wie wär's mit

Code: Alles auswählen

sed 's/./Aktueller\ Buchstabe ist:\ &\n/g' <<< "$INPUT"
(für INPUT="Hallo - Welt")
Ergibt:

Code: Alles auswählen

Aktueller Buchstabe ist: H
Aktueller Buchstabe ist: a
Aktueller Buchstabe ist: l
Aktueller Buchstabe ist: l
Aktueller Buchstabe ist: o
Aktueller Buchstabe ist:  
Aktueller Buchstabe ist: -
Aktueller Buchstabe ist:  
Aktueller Buchstabe ist: W
Aktueller Buchstabe ist: e
Aktueller Buchstabe ist: l
Aktueller Buchstabe ist: t

Wenn Leerzeile am Schluss stört, kann man die ja noch entfernen mit einem Umweg über printf oder irgendeinem sed-Trick.

tobo
Beiträge: 1964
Registriert: 10.12.2008 10:51:41

Re: (erledigt) Bash: Textstring in einzelne Buchstaben/Charaktere zerlegen

Beitrag von tobo » 19.02.2018 22:06:55

hikaru hat geschrieben: ↑ zum Beitrag ↑
19.02.2018 21:08:03
Ich verstehe noch nicht ganz was hier passiert, aber offenbar wird die Schleife nur einmal durchlaufen, gibt in diesem einen Durchlauf aber trotzdem alle Buchstaben aus. Das wird deutlich, wenn man wie ren22 einen fixen String mit ausgibt:
Das stimmt natürlich. Es wird nur ein Argument übergeben, weshalb i nach einem Schleifendurchlauf schon fertig befüllt ist, jeweils getrennt durch \n. Das war also offensichtlich ein Schnellschuss - so geht's nicht.

owl102

Re: (erledigt) Bash: Textstring in einzelne Buchstaben/Charaktere zerlegen

Beitrag von owl102 » 19.02.2018 22:54:33

tobo hat geschrieben: ↑ zum Beitrag ↑
19.02.2018 17:17:33
Entweder speicherst du dir den IFS und setzt ihn danach wieder auf den alten Wert:
Das geht aber nicht so einfach, da IFS nicht gesetzt und IFS="" unterschiedliche Auswirkungen haben. Nach deinem Code wird aber aus IFS nicht gesetzt zu IFS="".

Hier wäre zum Beispiel ein Code, der das berücksichtigt: https://unix.stackexchange.com/a/264947/167017

Am einfachsten löst man aber solche Probleme, indem man den Code (wenn möglich) in eine Subshell () packt, dann restauriert sich IFS am Ende automatisch.

Davon ab biete ich die 73ste Lösungs-Variante für das gestellte Problem:

Code: Alles auswählen

#!/bin/bash

string="hallo - welt"
while [[ $string ]]
do
  printf "Aktueller Buchstabe ist: %s\n" "${string:0:1}"
  string=${string:1}
done
Zuletzt geändert von owl102 am 20.02.2018 10:32:09, insgesamt 1-mal geändert.

tobo
Beiträge: 1964
Registriert: 10.12.2008 10:51:41

Re: (erledigt) Bash: Textstring in einzelne Buchstaben/Charaktere zerlegen

Beitrag von tobo » 20.02.2018 00:24:49

owl102 hat geschrieben: ↑ zum Beitrag ↑
19.02.2018 22:54:33
Das geht aber nicht so einfach, da IFS nicht gesetzt und IFS="" unterschiedliche Auswirkungen haben. Nach deinem Code wird aber aus IFS nicht gesetzt zu IFS="".
Stimmt, für den Fall das IFS initial nicht existiert ist so eine Rückzuweisung falsch. Das hatte ich so noch gar nicht auf dem Schirm - vielen Dank!

Antworten