Hallo,
ich hab das Problem, daß eine in der Schleife veränderte Variable außerhalb der Schleife nicht verändert wurde:
OCR_DATA="X" gocr scan.png | tac | while read LINE; do OCR_DATA="$OCR_DATA:$LINE" echo "$LINE" >> while.txt done echo "$OCR_DATA" > ocrdata.txt
gocr hat Daten erkannt und die werden auch in while.txt geschrieben. In ocrdata.txt kommt aber nur das vor der Schleife gesetzte X an.
Die beiden Textdateien sind nur zum Test, ich brauche letztlich nur den Wert aus OCR_DATA und das was sonst noch zeilenweise in der Schleife erzeugt wird. Die Daten sollen nicht erst auf die Platte geschrieben werden. Der String soll nur zur Kontrolle in eine DB geschrieben werden
Bei meiner Recherche bin ich an anderer Stelle auf das selbe Problem gestoßen, aber nicht auf eine Lösung:
http://www.netzmafia.de/skripten/unix/unix8.html ... Speicherbelegung Das Skript 'lsum' berechnet aus dem ls-Kommando den Gesamtspeicherplatz der ausgewählten Dateien. Einfacher geht es aber mit 'du'.
#!/bin/sh # Calculate the amount of space used by the specified files # Default is the actual directory SUM=0 TMPF=$HOME/$0$$ ls -l $* >$TMPF while read D1 D2 D3 D4 D5 REST ; do # lesen aus TMPF # Feld 5 enthaelt Groesse SUM=`expr $SUM + 0$D5 / 1024` done < $TMPF echo "$SUM KBytes" rm $TMPF
Preisfrage: Warum funktioniert folgende Variante nicht?
#!/bin/sh SUM=0 ls -l | while read D1 D2 D3 D4 D5 REST ; do SUM=`expr $SUM + 0$D5 / 1024` done echo "$SUM KBytes" ...
Hat hier vielleicht jemand eine Idee, woran das liegt?
Gruß Rico
Rico Koerner rico@netbreaker.de (Sa 13 Feb 2010 00:30:46 CET):
Hallo,
ich hab das Problem, daß eine in der Schleife veränderte Variable außerhalb der Schleife nicht verändert wurde:
OCR_DATA="X" gocr scan.png | tac | while read LINE; do OCR_DATA="$OCR_DATA:$LINE" echo "$LINE" >> while.txt done echo "$OCR_DATA" > ocrdata.txt
Weil Dein „while“ hinter eine Pipeline ist, ist es ein Sub-Process, also eine andere Shell.
Das sollte es tun:
OCR_DATA="X" gocr scan.png | tac | { while read LINE; do OCR_DATA="$OCR_DATA:$LINE" echo "$LINE" >> while.txt done echo "$OCR_DATA" > ocrdata.txt }
Alternativ könnte auch folgendes gehen: (hier läuft die while-Schleife dann in der „Parent“-Shell und das gocr/tac in einer Kindshell <(process substitution) wäre das Stichwort.
while read LINE; do …. done <(gocr scan.png | tac) echo "$OCR_DATA" > ocrdata.txt
Speicherbelegung Das Skript 'lsum' berechnet aus dem ls-Kommando den Gesamtspeicherplatz der ausgewählten Dateien. Einfacher geht es aber mit 'du'.
… den Script kommentiere ich lieber nicht.
#!/bin/sh SUM=0 ls -l | while read D1 D2 D3 D4 D5 REST ; do SUM=`expr $SUM + 0$D5 / 1024` done echo "$SUM KBytes"
Selbes Problem wie bei Dir.
Heiko
Am 13.2.2010 10:09, schrieb Heiko Schlittermann:
Weil Dein „while“ hinter eine Pipeline ist, ist es ein Sub-Process, also eine andere Shell.
Sowas hatte ich schon geahnt, nur fiel mir keine Lösung ein.
Das sollte es tun:
OCR_DATA="X" gocr scan.png | tac | { while read LINE; do OCR_DATA="$OCR_DATA:$LINE" echo "$LINE">> while.txt done echo "$OCR_DATA"> ocrdata.txt }
Werd ich mal probieren.
Alternativ könnte auch folgendes gehen: (hier läuft die while-Schleife dann in der „Parent“-Shell und das gocr/tac in einer Kindshell<(process substitution) wäre das Stichwort.
while read LINE; do …. done<(gocr scan.png | tac) echo "$OCR_DATA"> ocrdata.txt
So ähnlich hab ich es inzwischen gelöst: ... done << EOF $(gocr ...) EOF
Irgendwie wollte das ohne EOF bei mir direkt hinter done nicht klappen. Da war wohl ein < oder $ vor der Klammer zuviel bei mir.
… den Script kommentiere ich lieber nicht.
Ist auch nicht nötig. ;-)
Selbes Problem wie bei Dir.
Deshalb hab ich es ja drangehangen, damit hier keiner nach dem "Tippfehler" sucht, der es ja offensichtlich nicht war.
Danke.
Rico
Rico Koerner rico@netbreaker.de (Di 16 Feb 2010 20:21:28 CET):
Am 13.2.2010 10:09, schrieb Heiko Schlittermann:
Weil Dein „while“ hinter eine Pipeline ist, ist es ein Sub-Process, also eine andere Shell.
(…)
while read LINE; do …. done<(gocr scan.png | tac) echo "$OCR_DATA"> ocrdata.txt
So ähnlich hab ich es inzwischen gelöst: ... done << EOF $(gocr ...) EOF
Irgendwie wollte das ohne EOF bei mir direkt hinter done nicht klappen. Da war wohl ein < oder $ vor der Klammer zuviel bei mir.
Du machst Command-Substitution „$(gocr …)“, ich mache oben Process-Substitution „<(gocr …)“. Meine Variante kann theoretisch auch mit „unendlich“ vielen Daten umgehen, bei Dir werden die Daten im RAM zwischengelagert und dürfen selbst kein „EOF“ am Zeilenanfang enthalten.
Am 13.2.2010 10:09, schrieb Heiko Schlittermann:
Weil Dein „while“ hinter eine Pipeline ist, ist es ein Sub-Process, also eine andere Shell.
Das sollte es tun:
OCR_DATA="X" gocr scan.png | tac | { while read LINE; do OCR_DATA="$OCR_DATA:$LINE" echo "$LINE">> while.txt done echo "$OCR_DATA"> ocrdata.txt }
Soweit funktioniert das, hilft mir aber nicht wirklich weiter. Die ocrdata.txt war ja nur dort, um das zu prüfen. Jetzt erweitert sich die Subshell auf die {}. Die Daten werden aber zusammen mit weiteren am Ende der Datei weiterverarbeitet. Die Subshell soweit auszudehnen ist nicht sinnvoll.
Alternativ könnte auch folgendes gehen: (hier läuft die while-Schleife dann in der „Parent“-Shell und das gocr/tac in einer Kindshell<(process substitution) wäre das Stichwort.
while read LINE; do …. done<(gocr scan.png | tac)
syntax error: unexpected end of file
done<<(gocr scan.png | tac) syntax error near unexpected token `('
done<<$(gocr scan.png | tac) wirft den Rest der Datei mit in die Schleife
done<$(gocr scan.png | tac) Datei nicht gefunden
done << EOF $(gocr scan.png | tac) EOF
Lediglich die Variante mit dem HERE-Document funktioniert an dieser Stelle. Also bleibt es bei dieser Variante.
Gruß Rico
Rico Koerner rico@netbreaker.de (Fr 19 Feb 2010 23:40:05 CET):
Am 13.2.2010 10:09, schrieb Heiko Schlittermann:
(…)
while read LINE; do …. done<(gocr scan.png | tac)
syntax error: unexpected end of file
Sorry, sollte heißen:
… done < <(gocr scan.png | tac)
Dann klappt das.
Am 20.2.2010 21:37, schrieb Heiko Schlittermann:
Rico Koernerrico@netbreaker.de (Fr 19 Feb 2010 23:40:05 CET):
Am 13.2.2010 10:09, schrieb Heiko Schlittermann:
(…)
while read LINE; do …. done<(gocr scan.png | tac)
syntax error: unexpected end of file
Sorry, sollte heißen:
… done< <(gocr scan.png | tac)
Dann klappt das.
Aber erst nachdem ich das #!/bin/sh durch #!/bin/bash ersetzt hatte. :-(
ls -l /bin/sh
lrwxrwxrwx 1 root root 4 19. Mär 2009 /bin/sh -> bash
/bin/sh --version
GNU bash, version 3.2.39(1)-release (i486-pc-linux-gnu)
Dieselbe Version wird auch angezeigt, wenn ich den Aufruf im Skript einfüge, unabhängig davon ob ich die bash explizit auswähle.
Wieso reagiert das Skript dann weiter unten anders?
Davor gabs:
~/ocrtest.sh
~/ocrtest.sh: line 17: syntax error near unexpected token `<' ~/ocrtest.sh: line 17: ` done< <(gocr scan.png | tac)'
Gruß Rico
Rico Koerner wrote:
Am 20.2.2010 21:37, schrieb Heiko Schlittermann:
[...]
Dann klappt das.
Aber erst nachdem ich das #!/bin/sh durch #!/bin/bash ersetzt hatte. :-(
ls -l /bin/sh
lrwxrwxrwx 1 root root 4 19. Mär 2009 /bin/sh -> bash
/bin/sh --version
GNU bash, version 3.2.39(1)-release (i486-pc-linux-gnu)
Dieselbe Version wird auch angezeigt, wenn ich den Aufruf im Skript einfüge, unabhängig davon ob ich die bash explizit auswähle.
Wieso reagiert das Skript dann weiter unten anders?
man bash [...] If bash is invoked with the name sh, it tries to mimic the startup behavior of historical versions of sh as closely as possible, while conforming to the POSIX standard as well.
Mit anderen Worten, einige bash-Erweiterungen werden ignoriert.
Oder anders, wenn du bash als bash nutzen willst, rufe sie als bash auf :-)
Ciao, Thomas
Am 25.2.2010 09:49, schrieb Thomas Köhler:
man bash [...] If bash is invoked with the name sh, it tries to mimic the startup behavior of historical versions of sh as closely as possible, while conforming to the POSIX standard as well.
Ab und zu sollte man die Manpage eben gründlich lesen. :-/
Mit anderen Worten, einige bash-Erweiterungen werden ignoriert.
Das hab ich gemerkt.
Oder anders, wenn du bash als bash nutzen willst, rufe sie als bash auf :-)
Wenn ich gewußt hätte, das es eine bash-Funktionalität ist, wär ich eher drauf gekommen. Das zu ändern war bei der Fehlersuche dann auch so eine spontane Eingebung. Man lernt nie aus.
Danke.
Gruß Rico
lug-dd@mailman.schlittermann.de