3 Stimmen

Bash-Skript Schleife über Leitungseingabe

Ich gehe folgendermaßen vor, was grundsätzlich funktioniert. Das Skript versucht, einige Zeilen in eine Datei einzufügen, um sie neu zu schreiben.

Es werden jedoch alle Leerzeilen und auch alle Zeilenumbrüche entfernt. Das Hauptproblem ist, dass es die letzte Zeile der Datei nicht verarbeitet. Ich bin mir nicht sicher, warum.

     while read line; do
        <... process some things ...>
        echo ${line}>> "${ACTION_PATH_IN}.work"
     done < "${ACTION_PATH_IN}"

Was kann getan werden, um dies zu beheben?

5voto

Chris Johnsen Punkte 199970
while IFS= read -r line; do
    ## some work
    printf '%s\n' "$line" >> output
done < <(printf '%s\n' "$(cat input)")
  • Ein leerer IFS sagt read keine führenden und nachgestellten Leerzeichen zu entfernen.
  • read -r verhindert, dass ein Backslash am EOL eine Zeilenfortsetzung erzeugt.
  • Setzen Sie Ihre Parametersubstitution in doppelte Anführungszeichen ( "$line" ), um zu verhindern, dass die Shell Worttrennungen und Globbing an seinem Wert vornimmt.
  • Utilice printf '%s\n' anstelle von echo weil es zuverlässig ist, wenn es Werte verarbeitet wie -e , -n , usw.
  • < <(printf '%s\n' "$(cat input)") ist eine hässliche Art, den Inhalt von LF zu beenden. input . Andere Konstruktionen sind möglich, je nach Ihren Anforderungen (pipe statt redirect von Prozessersatz, wenn es in Ordnung ist, dass Ihr ganzes while läuft in einer Subshell).
    Es wäre vielleicht besser, wenn Sie sich vor der Verarbeitung vergewissern würden, dass die Datei mit LF abgeschlossen wurde.

3voto

ghostdog74 Punkte 305138

Am besten verwenden Sie ein Tool wie awk anstelle des Shells while Schleife. Erstens, awk ist für das Parsen/Manipulieren von Dateien gedacht, also für die Verarbeitung einer großen Datei, awk hat den Vorteil. Zweitens müssen Sie sich nicht darum kümmern, ob Sie den letzten Zeilenumbruch haben oder nicht (in Ihrem Fall).

Daher ist das Äquivalent zu Ihrer while read Schleife:

awk '{
  # process lines
  # print line > "newfile.txt"
}' file

1voto

Jonathan Leffler Punkte 694013

Ein möglicher Grund für das Nichtlesen der letzten Zeile ist, dass die Datei nicht mit einem Zeilenumbruch endet. Im Großen und Ganzen würde ich erwarten, dass es auch so funktioniert, aber das könnte der Grund sein.

Unter MacOS X (10.7.1) erhielt ich diese Ausgabe, die dem Verhalten entspricht, das Sie sehen:

$ /bin/echo -n Hi
Hi$ /bin/echo -n Hi > x
$ while read line; do echo $line; done < x
$

Die offensichtliche Lösung besteht darin, sicherzustellen, dass die Datei mit einem Zeilenumbruch endet.

0voto

Diego Sevilla Punkte 27639

Als Erstes verwenden Sie

echo "$line" >> ...

Beachten Sie die Anführungszeichen. Wenn Sie sie nicht setzen, entfernt die Shell selbst die Polsterung.

Was die letzte Zeile betrifft, so ist sie seltsam. Es könnte damit zu tun haben, ob die letzte Zeile der Datei mit einem \n oder nicht (es ist eine gute Praxis, dies zu tun, und fast jeder Editor wird dies für Sie tun).

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X