# [Bash] Problem mit While Schleife und Variable

## Finswimmer

Hi,

ich habe folgendes Skript:

```
#!/bin/bash

function query {

mysql -N  -utobi -ptest -A -Dtest -e "$1"

}

#count: Gibt an, wieviele User benachrichtigt wurden.

count=0

#Schleife ueber alle User ohne Admin

query "SELECT user_id FROM td_login WHERE user_id != 0" | tr '\t' '|' | while IFS='|' read user_id ; do             

echo 'user' $user_id

((count++))

echo $count

done

echo $count
```

Am Anfang wird count auf 0 gesetzt.

Innerhalb der Schleife wird count immer um eins erhört.

Am Ende gibt das Programm allerdings nur 0 aus. Also den Wert, der vorher schon gesetzt war.

Soweit ich das verstehe, wird in der while-Schleife eine Bash als Child-Programm erzeugt. Dort wird count gesetzt.

Aber der Weg zurück, dass aus einem Child die Variable von den Eltern gesetzt wird, geht nicht.

Wie mache ich das nun am Besten?

Vielen Dank

Tobi

P.S: Im Moment bin ich mit PHP und Java unterwegs. Deswegen stehe ich bei der Bash grade vor Rätsel....

----------

## 69719

Dies wäre eine Lösung.

```

#!/bin/bash

function query {

mysql -N  -utobi -ptest -A -Dtest -e "$1"

}

#count: Gibt an, wieviele User benachrichtigt wurden.

count=0

#Schleife ueber alle User ohne Admin

query "SELECT user_id FROM td_login WHERE user_id != 0" | tr '\t' '|' | while IFS='|' read user_id ; do             

echo 'user' $user_id

((count++))

echo $count | tee /tmp/count

done

count=$(cat /tmp/count)

rm -f /tmp/count

echo $count

```

----------

## py-ro

[wegeditiert]

@fin

Das Problem ist nicht die While Schleife sondern die Pipe.

Speichere die Ausgabe in einer Variablen zwischen und verarbeite diese, dann sollte es wie gewünscht funktionieren.

Alternativ benutze den <<<$(quer ...) als Operator, sollte auch gehen. (nicht getestet)

Bye 

Py

----------

## mv

Eine noch einfachere Lösung, die in vielen Fällen (so auch in diesem) geht: Kehre aus der subshell gar nicht zurück, sondern mache aus ihr das Hauptscript. 

```
query ... | {

 while IFS='|' read user_id

 do ...

  ...

 done

 echo $count

}
```

----------

## mv

 *escor wrote:*   

> Dies wäre eine Lösung.
> 
> ```
> tee /tmp/count
> ```
> ...

 

WARNUNG Dateien in world-writable Directories mit vorhersagbaren Namen sind ein massives Sicherheitsloch. Unbedingt vermeiden!

Also entweder mit mktemp die Datei schon vorher anlegen oder (was in diesem Fall möglich wäre) die Ausgabe über andere Filedescriptoren (etwa &3) mit exec umleiten. Oder - wenn die Ausgabe von query nicht gerade mehrere MB lang ist - mit $(query ...) oder 

```
<<EOF

`query ...`

EOF
```

 arbeiten. Die erwähnte Lösung mit << <(query ...) ist ein Bashismus.

Wo wir gerade bei Letzterem sind: Im ursprünglichen Skript gibt es ebenfalls zwei Bashismen, die leicht vermeidbar wären (dann liefe das Script auch mit der schnelleren dash): Statt der Definition "function query" ist der kompatible (und sogar besser lesbare) Code "query()", und statt des Bashismus ((count++)) kann man doch auch das POSIX count=$(( $count + 1 )) schreiben.

----------

## Finswimmer

Ich habe es nun mit mktemp gelöst.

Danke.

tobi

----------

