Jak usunąć znak nowej linii na końcu pliku?


35

Pozwól, że wyjaśnię charakter nowego znaku:

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

Tutaj możesz zobaczyć, że file1na końcu file2ma znak nowej linii, a nie ma.

Załóżmy teraz, że mam jeden file:

$ cat file
Hello
Welcome to
Unix
$

I chcę dodać and Linuxna końcu pliku, a następnie echo " and Linux" >> filezostanie dodany do nowej linii. Ale chcę ostatnią linię jakoUnix and Linux

Aby obejść ten problem, chcę usunąć znak nowej linii na końcu pliku. Dlatego jak usunąć znak nowej linii na końcu pliku?


6
Nie usuwaj go, po prostu użyj edytora tekstu. sed '$s/$/ and linux/'
123

Odpowiedzi:


29

Jeśli wszystko, co chcesz zrobić, to dodać tekst do ostatniego wiersza, dzięki sed bardzo łatwo. Zamień $(dopasowanie wzorca na końcu linii) tekstem, który chcesz dodać, tylko w liniach z zakresu $(co oznacza ostatnią linię).

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

które w systemie Linux można skrócić

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

Jeśli chcesz usunąć ostatni bajt z pliku, Linux (a dokładniej GNU coreutils) oferuje truncatepolecenie, co czyni to bardzo łatwym.

truncate -s -1 file

Sposób na POSIX to zrobić dd. Najpierw określ długość pliku, a następnie skróć go o jeden bajt mniej.

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

Zauważ, że oba te bezwarunkowo obcinają ostatni bajt pliku. Możesz najpierw sprawdzić, czy jest to nowy wiersz:

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

9
Znacznie lepszym sposobem na usunięcie nowej linii jest perl -pi -e 'chomp if eof' myfile. W porównaniu do truncatelub ddnie pozostawi cię z uszkodzonym plikiem, jeśli w myfilerzeczywistości nie miałby żadnych nowych linii.
Cześć Anioł

2
@ Hi-Angel Czy mogę polecić napisanie tego jako odpowiedzi? Myślę, że to byłaby bardzo dobra odpowiedź.
Simon Forsberg

@ SimonForsberg dzięki, gotowe .
Cześć Anioł

17

Możesz jednak usunąć znak nowej linii z linii poprzez tr -d '\n':

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

Możesz usunąć znak nowej linii na końcu pliku, używając następującego prostego sposobu:

  1. head -c -1 file

    Od 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

    z 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.
    

jest head -c -1 file | tee filebezpieczny? Czy nie teeobciąłby pliku przed uruchomieniem?
iruvar

1
@ 1_CR Rzeczywiście. Dwie strony rury zaczynają się równolegle, to kwestia wygranej w wyścigu. Ponieważ teemusi tylko otworzyć plik, podczas gdy headmusi czytać i zapisywać jego zawartość, teew praktyce wygra wyścig, z wyjątkiem czasami bardzo małych plików.
Gilles „SO- przestań być zły”

2
To nie usuwa ostatniej nowej linii, usuwa wszystkie nowe linie. IMO całkiem spora różnica.
Cześć Anioł

10

Możesz to osiągnąć za pomocą Perla jako:

perl -pi -e 'chomp if eof' myfile

W porównaniu do tego truncatelub ddnie pozostawi ci zepsutego pliku, jeśli w myfilerzeczywistości nie miał końcowych znaków nowej linii.

(odpowiedź jest zbudowana z komentarza i oparta na tej odpowiedzi )


Dziękuję Ci! Ta warunkowa metoda usuwania końca linii jest idealna.
xer0x

3

Oto jeden sposób sed- w ostatnim $wierszu pliku wyszukaj i zamień wszystko i wszystko ( .*) na „cokolwiek, co pasowałeś”, a następnie „i Linux”:

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

Jeszcze prostsze rozwiązanie, dzięki uprzejmości Izaaka , to:

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

To zastępuje (symboliczny) koniec wiersza podanym tekstem.


Izaak, podoba mi się ta sugestia! To jest prostsze / bardziej oczywiste. Zaktualizuję przy tym odpowiedź. Dziękuję Ci!
Jeff Schaller
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.