staging.inyokaproject.org

Bash: for-schleife mit Verarbeitung von Variablen

Status: Ungelöst | Ubuntu-Version: Ubuntu GNOME 16.04 (Xenial Xerus)
Antworten |

althoffc

Anmeldungsdatum:
7. Dezember 2015

Beiträge: Zähle...

Hallo,

ich möchte in einer For-Schleife mehrere Variablen mit ähnlichen Namen verarbeiten. Die Variablennamen unterscheiden sich nur durch einen Zähler, z.B. variable1, variable2, variable3, usw.

Ich habe es nicht hinbekommen mit folgender Schleife den Satz "Hallo was geht? " in der Schleife zu erzeugen.

Das zusammensetzen der Variablennamen funktioniert so nicht. Ist so etwas überhaupt möglich? Wie muss dann die Syntax lauten?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
satz=''
variable1="Hallo"
variable2="was"
variable3="geht?"

for i in 1 2 3 4 5
do
   echo " variable$i =  $variable$i"
   satz="$satz' '$variable$i"                        # Zum Schluss sollte satz="Hallo was geht? " beinhalten.
done

mrkramps Team-Icon

Avatar von mrkramps

Anmeldungsdatum:
10. Oktober 2006

Beiträge: 5523

Ich bin jetzt auf folgende Lösung gekommen:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
#!/bin/bash
variable1="Hallo"
variable2="was"
variable3="geht?"

for i in 1 2 3
do
    wort="variable"$i""
    satz="$satz""${!wort} "
done

echo "$satz"

Damit hat der Satz am Ende dann allerdings ein überflüssiges Leerzeichen:

Hallo was geht? 

Im Ausdruck ${!wort} sorgt das ! dafür, dass die Variable wort seinen Inhalt als Variable interpretiert und entsprechend deren Inhalt ausgibt (so oder so ähnlich). Ein Stichwort dazu ist „Bash Variable Variables“.

ChickenLipsRfun2eat Team-Icon

Anmeldungsdatum:
6. Dezember 2009

Beiträge: 12067

Ich würde das wohl mit einem Array versuchen:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
variable[0]="Hallo"
variable[1]="was"
variable[2]="geht?"

for i in {0..5}
 do
  if [ ${variable[$i]} ]
   then
    satz="$satz "${variable[$i]}
  fi
done

echo $satz

mrkramps Team-Icon

Avatar von mrkramps

Anmeldungsdatum:
10. Oktober 2006

Beiträge: 5523

Verdammt, das mit dem Leerzeichen hab ich gepflegt verkackt 😕

Sogar doppelt verkackt, weil mein erster Gedanke war das echo noch mit einer Pipe durch sed zu jagen um das angehängte Leerzeichen zu entfernen …

ChickenLipsRfun2eat Team-Icon

Anmeldungsdatum:
6. Dezember 2009

Beiträge: 12067

mrkramps schrieb:

Sogar doppelt verkackt, weil mein erster Gedanke war das echo noch mit einer Pipe durch sed zu jagen um das angehängte Leerzeichen zu entfernen …

Ich habe auch Quotingfehler drin. Es geht doch nicht um fertige 100%-Lösungen, sondern Richtungen. Und deine ist doch auch nicht verkehrt (und näher an den Vorgaben). Das "drumherum" wird dann so und so verändert und an das eigentliche Ziel angepasst ☺ Außerdem ist das mittels echo und pipe gar nicht so verkehrt, wenn man sieht wie das geht. Bei "Schleife" denke ich halt immer an "Array", weil man da bequem den Zähler direkt mitbenutzen kann.

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13242

ChickenLipsRfun2eat schrieb:

Ich habe auch Quotingfehler drin. Es geht doch nicht um fertige 100%-Lösungen, sondern Richtungen. Und deine ist doch auch nicht verkehrt (und näher an den Vorgaben). Das "drumherum" wird dann so und so verändert und an das eigentliche Ziel angepasst ☺

Aber welches Problem willst Du lösen? Arrays in der bash sind genau das richtige Mittel, um indizierte Zugriffe auf beliebig lange Listen zu machen. Es gibt aber auch noch andere Lösungen. Nach meiner Erfahrung komme ich meistens ohne Arrays aus.

Außerdem ist das mittels echo und pipe gar nicht so verkehrt, wenn man sieht wie das geht. Bei "Schleife" denke ich halt immer an "Array", weil man da bequem den Zähler direkt mitbenutzen kann.

In der bash gibt es ja auch:

1
2
3
4
5
6
$ for ((i=0;i<5;++i)); do echo $i; done
0
1
2
3
4

und

1
2
3
4
5
6
$ for i in {0..4}; do echo $i; done
0
1
2
3
4

track

Avatar von track

Anmeldungsdatum:
26. Juni 2008

Beiträge: 7174

Ok, der anständige Weg um sowas zu machen geht mit Arrays. Das ist auf jeden Fall sauber, richtig und zu empfehlen.

Allerdings hat die Bash - auch hier mal wieder - dafür auch eine unanständige Lösung parat, mit Parameter Expansion und Variable Indirection:

track@track:~$ variable1="Hallo"
track@track:~$ variable2="was"
track@track:~$ variable3="geht?"
track@track:~$ for i in ${!variable*} ; do
> echo "${!i}"
> done
Hallo
was
geht?
track@track:~$ for i in ${!variable*} ; do                  # alternativ kann man auch in einer Variable sammeln:
> satz+="${!i} "
> done
track@track:~$ echo "${satz/% /}"
Hallo was geht? 

... durchaus nicht als Vorschlag, sondern nur als Hinweis auf die schmutzigen Tricks der Bash.
(aber keine Sorge: die haben oft so schmutzige Nebenwirkungen, dass das dann auch keinen Spass mehr macht !)

LG,

track

Antworten |