Como removo o caractere de nova linha no final do arquivo?


34

Deixe-me esclarecer sobre o caractere de nova linha:

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

Aqui você pode ver que file1possui um caractere de nova linha no final, enquanto file2não possui.

Agora suponha que eu tenho um file:

$ cat file
Hello
Welcome to
Unix
$

E eu quero adicionar and Linuxno final do arquivo, em seguida, echo " and Linux" >> fileserá adicionado à nova linha. Mas eu quero a última linha comoUnix and Linux

Portanto, para contornar o problema, quero remover o caractere de nova linha no final do arquivo. Portanto, como faço para remover o caractere de nova linha no final do arquivo?


6
Não o remova, apenas use um editor de texto. sed '$s/$/ and linux/'
123

Respostas:


28

Se tudo o que você deseja fazer é adicionar texto à última linha, é muito fácil com o sed. Substitua $(correspondência de padrão no final da linha) pelo texto que você deseja adicionar, apenas nas linhas do intervalo $(que significa a última linha).

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

que no Linux pode ser reduzido para

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

Se você deseja remover o último byte de um arquivo, o Linux (mais precisamente o GNU coreutils) oferece o truncatecomando, o que facilita muito isso.

truncate -s -1 file

Uma maneira POSIX de fazer isso é com dd. Primeiro determine o tamanho do arquivo e, em seguida, trunque-o para um byte a menos.

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

Observe que esses dois truncam incondicionalmente o último byte do arquivo. Convém verificar se é uma nova linha primeiro:

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
Muito melhor maneira de remover uma nova linha de fuga é perl -pi -e 'chomp if eof' myfile. Comparado truncateou ddnão vai deixar você com um arquivo quebrado, se myfilena verdade não houver novas linhas à direita.
Hi-Angel

2
@ Hi-Angel Posso recomendar escrever isso como resposta? Eu acho que seria uma resposta muito boa.
Simon Forsberg

@SimonForsberg obrigado, pronto .
Hi-Angel

17

No entanto, você pode remover o caractere de nova linha da linha tr -d '\n':

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

Você pode remover o caractere de nova linha no final do arquivo usando a seguinte maneira fácil:

  1. head -c -1 file

    De 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

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

está head -c -1 file | tee fileseguro? Não teetruncaria o arquivo antes de iniciar?
Iruvar

11
@ 1_CR Realmente. Os dois lados do tubo começam em paralelo, é uma questão de quem vence a corrida. Uma vez que teeapenas tem que abrir o arquivo, enquanto que headtem que ler e escrever seu conteúdo, teena prática vencerá a corrida, exceto às vezes para arquivos muito pequenos.
Gilles 'SO- stop be evil' ''

2
Isso não remove a última nova linha, remove todas as novas linhas. IMO uma grande diferença.
Hi-Angel

9

Você pode conseguir isso com o perl como:

perl -pi -e 'chomp if eof' myfile

Comparado truncateou ddisso não vai deixar você com um arquivo quebrado, se myfilena verdade não houver novas linhas à direita.

(a resposta é construída a partir do comentário e com base nessa resposta )


Obrigado! Esse método condicional de remoção está seguindo a nova linha é perfeito.
xer0x 04/11

2

Aqui está uma maneira de sed- na última ( $) linha do arquivo, pesquise e substitua tudo e qualquer coisa ( .*) por "o que você correspondeu", seguido de "e Linux":

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

Uma solução ainda mais simples, cortesia de Isaac , é:

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

Isso substitui o final de linha (simbólico) pelo texto fornecido.


Isaac, eu gosto dessa sugestão! É mais simples / mais óbvio. Vou atualizar a resposta com ele. Obrigado!
Jeff Schaller
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.