Come rimuovo il carattere di nuova riga alla fine del file?


35

Vorrei chiarire il personaggio di Newline:

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

Qui puoi vedere che file1ha un carattere newline alla fine, mentre file2non lo è.

Ora supponiamo che ne abbia uno file:

$ cat file
Hello
Welcome to
Unix
$

E voglio aggiungere and Linuxalla fine del file, quindi echo " and Linux" >> fileverrà aggiunto a newline. Ma voglio l'ultima riga comeUnix and Linux

Quindi, per aggirare il problema, desidero rimuovere il carattere di nuova riga alla fine del file. Pertanto, come posso rimuovere il carattere di nuova riga alla fine del file?


6
Non rimuoverlo, basta usare un editor di testo. sed '$s/$/ and linux/'
123

Risposte:


29

Se tutto ciò che vuoi fare è aggiungere del testo all'ultima riga, con sed è molto semplice. Sostituisci $(corrispondenza dei pattern alla fine della riga) con il testo che desideri aggiungere, solo sulle righe nell'intervallo $(che significa l'ultima riga).

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

che su Linux può essere abbreviato

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

Se si desidera rimuovere l'ultimo byte in un file, Linux (più precisamente GNU coreutils) offre il truncatecomando, il che lo rende molto semplice.

truncate -s -1 file

Un modo POSIX per farlo è con dd. Per prima cosa determinare la lunghezza del file, quindi troncarlo a un byte in meno.

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

Si noti che entrambi questi troncano incondizionatamente l'ultimo byte del file. Potresti voler verificare prima che sia una newline:

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
Molto meglio modo per rimuovere un carattere di fine riga è perl -pi -e 'chomp if eof' myfile. Rispetto truncateo ddnon ti lascerà con un file rotto se in myfilerealtà non aveva nuove righe finali.
Hi-Angel,

2
@ Ciao Angelo Posso raccomandare di scriverlo come risposta? Penso che sarebbe un'ottima risposta.
Simon Forsberg,

@SimonForsberg grazie, fatto .
Hi-Angel,

17

Tuttavia, puoi rimuovere il carattere di nuova riga dalla riga tr -d '\n':

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

Puoi rimuovere il carattere di nuova riga alla fine del file usando la seguente semplice procedura:

  1. head -c -1 file

    Da 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

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

è head -c -1 file | tee filesicuro? Non teetroncare il file prima di iniziare?
Iruvar,

1
@ 1_CR In effetti. I due lati del tubo iniziano in parallelo, dipende da chi vince la gara. Dal momento teeche deve solo aprire il file, mentre headdeve leggere e scrivere il suo contenuto, teein pratica vincerà la gara tranne a volte per file molto piccoli.
Gilles 'SO- smetti di essere malvagio' l'

2
Questo non rimuove l'ultima nuova riga, rimuove tutte le nuove righe. IMO una differenza abbastanza grande.
Hi-Angel,

10

Puoi farlo con perl come:

perl -pi -e 'chomp if eof' myfile

Rispetto truncateo ddquesto non ti lascerà con un file rotto se in myfilerealtà non aveva nuove righe finali.

(la risposta è costruita dal commento e basata su questa risposta )


Grazie! Questo metodo condizionato di rimozione di Newline è perfetto.
xer0x

3

Ecco un modo con sed- sull'ultima ( $) riga del file, cerca e sostituisci qualsiasi cosa ( .*) con "qualunque cosa abbini" seguito da "e Linux":

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

Una soluzione ancora più semplice, per gentile concessione di Isaac , è:

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

Questo sostituisce la fine (simbolica) della riga con il testo dato.


Isacco, mi piace quel suggerimento! È più semplice / più ovvio. Aggiornerò la risposta con esso. Grazie!
Jeff Schaller
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.