PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : BASH: Warum sind "for" und "while" nicht synonym in diesem Beispiel?



qeldroma
03-09-2008, 14:55
Hallo zusammen,

ich habe da ein Ergebnis, was ich nicht verstehe:

Ich habe ein Skript (test_script.sh), welches ich zeilenweise aus einer csv-Datei betanke.
Dieses Skript schmeißt die Exitcodes 0 oder 1.

Interessanterweise steigt bei folgenden zwei Beispielen das Skript mit der while-schleife sofort nach einmaligem Ausführen von "test_script.sh" aus, egal ob der exitcode von "test_script.sh" 0 oder 1 war? Die for-Schleife arbeitet wie erwartet.

Beispiel "for":

for line in `cat csv-file.csv`;do test_script.sh $line;done
Beispiel "while":

cat csv-file.csv|while read line;do test_script.sh $line;done

Wie habe ich mir das zu erklären?

Noch spannender war, daß ich nicht mal mit "trap" dieses verhindern konnte, also

cat csv-file.csv|while read line;do trap "" SIGHUP EXIT;test_script.sh $line;done

oder durch

cat csv-file.csv|while read line; test_script.sh $line && echo || echo;done

Kann mich da jemand aufklären?

Gruß und danke, Florian

ContainerDriver
03-09-2008, 16:07
Hallo,

meine Vermutung ist, dass read bis zum Newline liest, die for-Schleife trennt den String aber beim IFS auf. Bei dem Beispiel mit der while-Schleife würde dein Skript dann mehrere Argumente bekommen.
Wie viele Zeilen hat denn die cvs-Datei?

Gruß, auch Florian

qeldroma
03-09-2008, 16:09
40 oder mehr Zeilen...

Hmm.... Na gut, bei einem solchen For-Konstrukt scheint er ja ofensichtlich sich am Zeilenumbruch nicht zu stören.

Ok, muß mal drüber nachdenken...

Gruß, Florian

ContainerDriver
03-09-2008, 16:18
40 oder mehr Zeilen...
Dann verstehe ich aber nicht, warum die while-Schleife nur einmal durchlaufen wird. Mit diesem Minimalbeispiel funktioniert es nämlich:



[florian@leuchtturm1 tmp]$ cat test.cvs|while read line; do echo $line; done;
zeile1.1,zeile1.2
zeile2.1,zeile2.2
zeile3.1,zeile3.2
[florian@leuchtturm1 tmp]$ for line in `cat test.cvs`; do echo $line; done;
zeile1.1,zeile1.2
zeile2.1,zeile2.2
zeile3.1,zeile3.2


bzw. die Datei mit Leerzeichen nach den Kommas:



[florian@leuchtturm1 tmp]$ cat test.cvs|while read line; do echo $line; done;
zeile1.1, zeile1.2
zeile2.1, zeile2.2
zeile3.1, zeile3.2
[florian@leuchtturm1 tmp]$ for line in `cat test.cvs`; do echo $line; done;
zeile1.1,
zeile1.2
zeile2.1,
zeile2.2
zeile3.1,
zeile3.2
.

jan61
03-09-2008, 20:53
Moin,

im Normalfall dürfte sich auch die while-Schleife nicht beenden. Ich sehe 2 mögliche Ursachen:

1. Dein test_script.sh reagiert anders, wenn es eine komplette Zeile geliefert kriegt (wie es in der while-Variante der Fall ist) als bei einzelnen Argumenten (wie ContainerDriver schon schrieb, liefert die for-Schleife jedes durch IFS - im Normalfall Tab, Whitespace und Newline - getrennte Feld als einzelnes Argument). Setze mal statt des test_script-Aufrufs ein einfaches echo $line ein und schau Dir das Ergebnis an. Wenn dann while durchläuft, dann musst Du in Deinem Script weitersuchen.

2. Deine Datei enthält irgendwelchen Zeichenmurks. Schau Dir mal die Datei im Hex-Code an: od -cx test.cvs | less

Vielleicht hilft Dir auch das hier: http://www.jan-trippler.de/de/script_tipps/loops.html oder http://www.jan-trippler.de/de/script_tipps/dos.html

Jan