# [bash] Verständnisfrage zu select und read

## 3PO

Hallo Zusammen,

ich habe hier ein kleines Problem mit einem BASH Script.

das kleine Script sieht so aus:

```
#!/bin/bash

PS3="Ihre Wahl : "

select auswahl in "Punkt 1" "Punkt 2" "Punkt 3" "Punkt 4" Ende

do

   case "$auswahl" in

      Ende)  echo "Ende"; break ;;

        "")  echo "Ungültige Auswahl" ;;

         *)  echo "Sie haben $auswahl gewählt"

   esac

done
```

Was auch funktioniert:

```
server01 test # ./test.sh

1) Punkt 1

2) Punkt 2

3) Punkt 3

4) Punkt 4

5) Ende

Ihre Wahl :
```

Wenn ich nun aber die "Punkte" aus einer Datei laden will, dann geht das nicht:

```
#!/bin/bash

PUNKT=$(while read line; do echo -en $line" "; done < punkt.txt)

PS3="Ihre Wahl : "

select auswahl in "$PUNKT" Ende

do

   case "$auswahl" in

      Ende)  echo "Ende"; break ;;

        "")  echo "Ungültige Auswahl" ;;

         *)  echo "Sie haben $auswahl gewählt"

   esac

done
```

punkt.txt:

```
server01 test # cat punkt.txt

Punkt 1

Punkt 2

Punkt 3

Punkt 4

server01 test #
```

Das ist dann die Ausgabe:

```
server01 test # ./test2.sh

1) Punkt 1 Punkt 2 Punkt 3 Punkt 4

2) Ende

Ihre Wahl :
```

Wenn ich die Leerzeichen weglasse, dann geht es.

Da ich aber die Leerzeichen benötige, würde es mich schon interessieren, wie ich das gebacken bekomme?

----------

## reini123

die Variable nicht geschützt durch " übergeben sollte Dir helfen.

```
select auswahl in $PUNKT Ende
```

also $PUNKTE ohne " und somit nicht als String.

----------

## 3PO

Dann sieht das Ergebnis so aus:

```
server01 test # ./test2.sh

1) Punkt  3) Punkt  5) Punkt  7) Punkt  9) Ende

2) 1      4) 2      6) 3      8) 4

Ihre Wahl :
```

----------

## reini123

Ich vermute mal es stoert Dich die Standardausgabe neben einander^^

entwerde script per ". ./test2.sh" anstatt "./test2.sh" aufrufen oder COLUMNS definieren.

```
#!/bin/bash

PUNKT=$(while read line; do echo -en "$line "; done < punkt.txt)

WORD=`echo "$PUNKT"|wc -w` #Anzahl der Auswahlkriterien in Var WORD definieren.

COLUMNS="$WORD" #COLUMNS auf die jeweilige Anzahl setzen 

PS3="Ihre Wahl : "
```

Ich hoffe das hilft Dir   :Very Happy:   sonst wüsste ich auch nicht weiter   :Shocked: 

Mƒg

----------

## 3PO

@reini123,

kann es sein, dass Du mein o.g. Problem nicht richtig verstanden hast?

Es geht darum, die Menü Items mit Leerzeichen darzustellen, wobei ich die Items aus ein er Datei auslesen will.

----------

## reini123

Hmm ...sry,

ja hab es falsch verstanden.

ausser 

```
PUNKT=$(while read line; do echo -en $line" "|sed 's/ /_/g'; done < punkt.txt)
```

fällt mir im Moment nichts ein.

Aber ein interessantes Problem das sich scheinbar auch nicht über array lösen läst  :Shocked: 

Bin schon gespannt ob irgendwer sonst die Lösung weis   :Laughing: 

[/code]

----------

## Yamakuzure

Die Lösung ist 'read' auf ein Array zu benutzen:

```
 ~/tmp $ cat test3.sh

#!/bin/bash

IFS=$(echo -en "\t") read -ra PUNKT <<<"$(cat punkt.txt | tr '\n' '\t')"

# Zum Anschauen:

# declare -p PUNKT

# echo

PS3="Ihre Wahl : "

select auswahl in "${PUNKT[@]}" Ende

do

   case "$auswahl" in

      Ende)  echo "Ende"; break ;;

        "")  echo "Ungültige Auswahl" ;;

         *)  echo "Sie haben $auswahl gewählt"

   esac

done

 ~/tmp $ ./test3.sh

1) Punkt 1

2) Punkt 2

3) Punkt 3

4) Punkt 4

5) Ende

Ihre Wahl : 5

Ende
```

Erklärung:

IFS=$(echo -en "\t")

Für 'read' werden Wörter hiermit ausschließlich per Tabulator getrennt.

read -ra PUNKT

Lese den folgenden Input in ein Array (-a) und ignoriere Backslashes (-r). Mit Letzterem bist du in "punkt.txt" etwas flexibler.

<<<"$(cat punkt.txt | tr '\n' '\t')"

Input (<<<) aus deiner "punkt.txt", 'tr' ersetzt alle Zeilenumbrüche durch Tabulator.

----------

## reini123

Danke   :Very Happy: 

```
#!/bin/bash

IFS=$'\n'

PUNKT=`while read line; do echo "$line"; done < punkt.txt`

COLUMNS=0

PS3="Ihre Wahl : "

select auswahl in $PUNKT Ende

do

   case "$auswahl" in

      Ende)  echo "Ende"; break ;;

        "")  echo "Ungültige Auswahl" ;;

         *)  echo "Sie haben $auswahl gewählt"

   esac

done

```

bin auch gerade auf IFS gekommen   :Very Happy: 

Halbe Nacht ist mir das nicht aus den Kopf gegangen ... da war doch was   :Rolling Eyes: 

----------

## 3PO

1000 THX @ Yamakuzure,

funktioniert hervorragend!   :Wink:   :Very Happy: 

Ich habe es mal etwas erweitert, dass ich aus der Schleife komme,

```
#!/bin/bash

IFS=$(echo -en "\t") read -ra PUNKT <<<"$(cat punkt.txt | tr '\n' '\t')"

# Zum Anschauen:

# declare -p PUNKT

# echo

PS3="Ihre Wahl : "

select auswahl in "${PUNKT[@]}" Ende

do

   case "$auswahl" in

      Ende)

        echo "Ende"

        break

        ;;

       "")  

        echo "Ungültige Auswahl"

        ;;

        *)

        echo "Sie haben $auswahl gewählt"

        break

        ;;

   esac

done

```

Die Frage ist nun, ob es eine Möglichkeit gibt, die gemachte Eingabe abzufragen?

Ich meine, wenn ich z.B, "2" eingebe, wie kann ich das ausgeben?

"$auswahl" gibt ja den Text aus, ich hätte aber gerne die Ziffern, geht  das überhaupt?

----------

## reini123

Wenn ich Dich nicht wieder falsch verstehe brauchst du REPLY ( The default variable for the read builtin. )

```
 echo "Sie haben "$REPLY" gewählt"
```

Ich hoffe Du meinst das?   :Very Happy: 

----------

## Yamakuzure

 *reini123 wrote:*   

> Wenn ich Dich nicht wieder falsch verstehe brauchst du REPLY ( The default variable for the read builtin. )
> 
> ```
>  echo "Sie haben "$REPLY" gewählt"
> ```
> ...

 Kurzer Test:

```
 ~/tmp $ cat test3.sh

#!/bin/bash

IFS=$(echo -en "\t") read -ra PUNKT <<<"$(cat punkt.txt | tr '\n' '\t')"

PS3="Ihre Wahl : "

select auswahl in "${PUNKT[@]}" Ende

do

    case "$auswahl" in

        Ende)

            echo "Ende"

            break

            ;;

        "")

            echo "Ungültige Auswahl"

            ;;

        *)

            echo "Sie haben $REPLY ($auswahl) gewählt"

            break

            ;;

    esac

done

 ~/tmp $ ./test3.sh

1) Punkt 1

2) Punkt 2

3) Punkt 3

4) Punkt 4

5) Ende

Ihre Wahl : 3

Sie haben 3 (Punkt 3 ) gewählt
```

Funzt!  :Smile: 

Dass nach dem "Punkt 3" in der Antwort noch ein Leerzeichen auftaucht müsste man noch beheben, aber ansonsten läuft das.

----------

## reini123

Die Leerzeichen einfach wegschneiden am Zeilenende, also wenn die sonst nicht gebraucht werden  :Question: 

```
IFS=$(echo -en "\t") read -ra PUNKT <<<"$(cat punkt.txt |sed 's/ *$//'| tr '\n' '\t')"
```

ZB mit sed   :Very Happy: 

Hoffe das funzt   :Cool: 

----------

## 3PO

Nun, das ist nicht, was ich gemeint habe.

Ich möchte wissen, welche Taste gedrückt wurde.

----------

## Yamakuzure

 *3PO wrote:*   

> Nun, das ist nicht, was ich gemeint habe.
> 
> Ich möchte wissen, welche Taste gedrückt wurde.

 Was fehlt bei 

```
Ihre Wahl : 3 

Sie haben 3 (Punkt 3 ) gewählt
```

 denn? Da steht doch, welche Taste gedrückt wurde...

----------

## reini123

Vielleicht gehts mit

```
echo -e "Sie haben Taste \033[33m-->\033[0m\033[41m$REPLY\033[0m\033[33m<--\033[0m gedrueckt und ($auswahl) gewählt"
```

 :Cool:   :Laughing: 

Ps.: Kleine Fonts sind eine Verschwoerung gegen uns aelteren Leute   :Very Happy: 

----------

## 3PO

Sorry, ich hatte das: 

 *Quote:*   

> [...] REPLY ( The default variable for the read builtin. ) 

 

total überlesen.   :Rolling Eyes: 

----------

