Wie entferne ich Newline-Zeichen am Ende der Datei?

33

Lassen Sie mich den Newline-Charakter klarstellen:

$ echo Hello > file1 ; cat file1
Hello
$ echo -n  Hello > file2 ; cat file2
Hello$ 

Hier sehen Sie, dass file1am Ende ein Zeilenumbruchszeichen steht, das file2aber nicht steht.

Angenommen, ich habe einen file:

$ cat file
Hello
Welcome to
Unix
$

Und ich möchte and Linuxam Ende der Datei hinzufügen , dann echo " and Linux" >> filewird zu newline hinzugefügt. Aber ich möchte die letzte Zeile alsUnix and Linux

Um das Problem zu umgehen, möchte ich das Zeilenumbruchzeichen am Ende der Datei entfernen. Daher Wie entferne ich das Newline-Zeichen am Ende der Datei?

Pandya
quelle
6
Entfernen Sie es nicht, sondern verwenden Sie einfach einen Texteditor. sed '$s/$/ and linux/'
123.

Antworten:

27

Wenn Sie nur Text in die letzte Zeile einfügen möchten, ist das mit sed ganz einfach. Ersetzen Sie $(Musterübereinstimmung am Ende der Zeile) durch den Text, den Sie hinzufügen möchten, nur für Zeilen im Bereich $(dh die letzte Zeile).

sed '$ s/$/ and Linux/' <file >file.new &&
mv file.new file

was unter Linux zu verkürzen ist

sed -i '$ s/$/ and Linux/' file

Wenn Sie das letzte Byte in einer Datei entfernen möchten, bietet Linux (genauer gesagt GNU coreutils) den truncateBefehl an, was dies sehr einfach macht.

truncate -s -1 file

Ein POSIX-Weg, dies zu tun, ist mit dd. Ermitteln Sie zuerst die Dateilänge und kürzen Sie sie dann auf ein Byte weniger.

length=$(wc -c <file)
dd if=/dev/null of=file obs="$((length-1))" seek=1

Beachten Sie, dass beide das letzte Byte der Datei unbedingt abschneiden. Vielleicht möchten Sie zuerst überprüfen, ob es sich um eine neue Zeile handelt:

length=$(wc -c <file)
if [ "$length" -ne 0 ] && [ -z "$(tail -c -1 <file)" ]; then
  # The file ends with a newline or null
  dd if=/dev/null of=file obs="$((length-1))" seek=1
fi
Gilles 'SO - hör auf böse zu sein'
quelle
9
Ein viel besserer Weg, um einen nachgestellten Zeilenumbruch zu entfernen, ist perl -pi -e 'chomp if eof' myfile. Im Vergleich zu truncateoder ddes wird Sie nicht mit einer kaputten Datei myfilezurücklassen, wenn Sie tatsächlich keine nachgestellten Zeilenumbrüche hatten.
Hi-Angel,
2
@ Hi-angel Darf ich das als Antwort empfehlen? Ich denke das wäre eine sehr gute Antwort.
Simon Forsberg
@ SimonForsberg danke, fertig .
Hi-Angel,
17

Sie können das Zeilenumbruchzeichen jedoch wie folgt aus der Zeile entfernen tr -d '\n':

$ echo -e "Hello"
Hello
$ echo -e "Hello" | tr -d '\n'
Hello$

Sie können das Zeilenumbruchzeichen am Ende der Datei auf folgende einfache Weise entfernen:

  1. head -c -1 file

    Von man head:

    -c, --bytes=[-]K
              print the first K bytes of each file; with the leading '-',
              print all but the last K bytes of each file
  2. truncate -s -1 file

    von man truncate:

    -s, --size=SIZE
              set or adjust the file size by SIZE

    SIZE is an integer and optional unit (example: 10M is 10*1024*1024).
    Units are K, M, G, T, P, E, Z, Y (powers of 1024) or KB, MB, ... (powers of 1000).
    
    SIZE  may  also be prefixed by one of the following modifying characters: 
    '+' extend by, '-' reduce by, '<' at most, '>' at least, '/' round down to multiple of, '%' round up to multiple of.
Pandya
quelle
ist head -c -1 file | tee filesicher? Würde teedie Datei vor dem Start nicht abgeschnitten?
Iruvar
1
@ 1_CR In der Tat. Die beiden Seiten der Pipe starten parallel, es kommt darauf an, wer das Rennen gewinnt. Da teedie Datei nur geöffnet werden muss, während headder Inhalt gelesen und geschrieben teewerden muss, gewinnt das Rennen in der Praxis mit Ausnahme von manchmal sehr kleinen Dateien.
Gilles 'SO- hör auf böse zu sein'
2
Dies entfernt nicht den letzten Zeilenumbruch, sondern alle Zeilenumbrüche. IMO ein ziemlicher Unterschied.
Hi-Angel,
8

Dies erreichen Sie mit perl als:

perl -pi -e 'chomp if eof' myfile

Im Vergleich zu truncateoder dddas wird Sie nicht mit einer kaputten Datei myfilezurücklassen, wenn Sie tatsächlich keine nachgestellten Zeilenumbrüche hatten.

(Die Antwort wird aus dem Kommentar erstellt und basiert auf dieser Antwort. )

Hallo Engel
quelle
Vielen Dank! Diese bedingte Methode zum Entfernen von Zeilenumbrüchen ist perfekt.
xer0x
2

Hier ist eine Möglichkeit : Suchen und ersetzen Sie sedin der letzten ( $) Zeile der Datei alles und .*jeden ( ) durch "was auch immer Sie gefunden haben", gefolgt von "und Linux":

sed '$s/\(.*\)/\1 and Linux/' file

Eine noch einfachere Lösung, mit freundlicher Genehmigung von Isaac , ist:

sed '$s/$/ and Linux/' file

Dies ersetzt das (symbolische) Zeilenende durch den angegebenen Text.

Jeff Schaller
quelle
Isaac, ich mag diesen Vorschlag! Es ist einfacher / offensichtlicher. Ich werde die Antwort damit aktualisieren. Vielen Dank!
Jeff Schaller