De que adianta adicionar uma nova linha ao final de um arquivo?

126

Alguns compiladores (especialmente C ou C ++) fornecem avisos sobre:

No new line at end of file

Eu pensei que este seria um problema somente para programadores C, mas o github exibe uma mensagem na visão de commit:

\ No newline at end of file

para um arquivo PHP.

Eu entendo o pré-processador explicado em este tópico , mas o que isso tem a ver com o PHP? É a mesma include() coisa ou está relacionada ao tópico \r\n vs \n ?

Qual é o sentido de ter uma nova linha no final de um arquivo?

    
por Ps0ke 14.08.2011 / 21:29

6 respostas

143

Não se trata de adicionar uma nova linha extra no final de um arquivo, mas de não remover a nova linha que deveria estar lá.

Um arquivo de texto , em unix, consiste em uma série de linhas , cada uma das quais termina com um caractere de nova linha ( \n ). Um arquivo que não está vazio e não termina com uma nova linha não é, portanto, um arquivo de texto.

Utilitários que devem operar em arquivos de texto podem não lidar bem com arquivos que não terminam com uma nova linha; utilitários históricos do Unix podem ignorar o texto após a última nova linha, por exemplo. Os utilitários do GNU têm uma política de se comportar de maneira decente com arquivos que não são de texto, assim como a maioria dos outros utilitários modernos, mas você ainda pode encontrar um comportamento estranho com arquivos que estão faltando uma nova linha final¹.

Com o GNU diff, se um dos arquivos que estão sendo comparados termina com uma nova linha, mas não com o outro, é necessário observar esse fato. Como diff é orientado a linhas, ele não pode indicar isso armazenando uma nova linha para um dos arquivos, mas não para os outros - as novas linhas são necessárias para indicar onde cada linha no arquivo diff é iniciada e termina. Então o diff usa esse texto especial \ No newline at end of file para diferenciar um arquivo que não termina em uma nova linha de um arquivo que fez.

A propósito, em um contexto C, um arquivo de origem é composto de uma série de linhas. Mais precisamente, uma unidade de tradução é visualizada em uma implementação definida como uma série de linhas, cada uma das quais deve terminar com um caractere de nova linha ( n1256 §5.1.1.1). Em sistemas unix, o mapeamento é direto. No DOS e no Windows, cada seqüência CR LF ( \r\n ) é mapeada para uma nova linha ( \n ; isso é o que sempre acontece ao ler um arquivo aberto como texto nesses sistemas operacionais). Existem alguns sistemas operacionais que não possuem um caractere de nova linha, mas possuem registros de tamanho fixo ou variável; nesses sistemas, o mapeamento dos arquivos para a origem C introduz um \n no final de cada registro. Embora isso não seja diretamente relevante para o unix, isso significa que, se você copiar um arquivo de origem C sem a nova linha final para um sistema com arquivos de texto baseados em registros, copie-o de volta, ou você acabará com o arquivo incompleto. última linha truncada na conversão inicial ou uma nova linha extra inserida nela durante a conversão inversa.

Exemplo: a saída da classificação GNU sempre termina com uma nova linha. Portanto, se o arquivo foo não tiver sua nova linha final, você verá que sort foo | wc -c informa mais um caractere do que cat foo | wc -c .

    
por 15.08.2011 / 18:10
33

Não necessariamente o motivo, mas uma conseqüência prática de arquivos que não terminam com uma nova linha:

Considere o que aconteceria se você quisesse processar vários arquivos usando cat . Por exemplo, se você quisesse encontrar a palavra foo no início da linha em três arquivos:

cat file1 file2 file3 | grep -e '^foo'

Se a primeira linha no arquivo3 começar com foo , mas o arquivo2 não tiver uma% final\n após sua última linha, essa ocorrência não será encontrada pelo grep, porque a última linha no arquivo2 e a primeira linha file3 seria visto pelo grep como uma única linha.

Então, por consistência e para evitar surpresas, tento manter meus arquivos sempre terminando com uma nova linha.

    
por 18.08.2011 / 21:01
12

Existem dois aspectos:

  1. Existem / foram alguns compiladores C que não podem analisar a última linha se ela não terminar com uma nova linha. O padrão C especifica que um arquivo C deve terminar com uma nova linha (C11, 5.1.1.2, 2.) e que uma última linha sem uma nova linha produz um comportamento indefinido (C11, J.2, 2º item). Talvez por razões históricas, porque algum fornecedor de tal compilador fazia parte do comitê quando o primeiro padrão foi escrito. Assim, o aviso pelo GCC.

  2. diff programs (como usado por git diff , github etc.) mostram diferenças de linha a linha entre os arquivos. Eles costumam imprimir uma mensagem quando apenas um arquivo termina com uma nova linha, porque senão você não veria essa diferença. Por exemplo, se a única diferença entre dois arquivos for a presença do último caractere de nova linha, sem a dica, pareceria que os dois arquivos eram os mesmos, quando diff e cmp retornam um sucesso desigual de código de saída e as somas de verificação dos arquivos (por exemplo, via md5sum ) não correspondem.

por 14.08.2011 / 22:29
7

O \ No newline at end of file que você recebe do github aparece no final de um patch (em diff formato , consulte a nota no final da seção "Formato unificado").

Os compiladores não se importam se existe uma nova linha ou não no final de um arquivo, mas git (e os diff / patch utilitários) precisam levar isso em consideração. Existem muitas razões para isso. Por exemplo, esquecer de adicionar ou remover uma nova linha no final de um arquivo alteraria seu hashsum ( md5sum / sha1sum ). Além disso, os arquivos nem sempre são programas, e um \n final pode fazer alguma diferença.

Nota : Sobre o aviso dos compiladores C, acho que eles insistem em uma nova linha final para propósitos de compatibilidade com versões anteriores. Os compiladores muito antigos podem não aceitar a última linha se ela não terminar com \n (ou outra sequência de caracteres de fim de linha dependente do sistema).

    
por 14.08.2011 / 22:03
2

Há também o ponto de manter o histórico de diferenças. Se um arquivo terminar sem um caractere de nova linha, a inclusão de qualquer coisa no final do arquivo será visualizada pelos utilitários de comparação como uma alteração na última linha (porque \n está sendo adicionado a ele).

Isso pode causar resultados indesejados com comandos como git blame e hg annotate .

    
por 09.09.2015 / 20:25
2

POSIX, este é um conjunto de padrões especificados pelo IEEE para manter a compatibilidade entre sistemas operacionais.

Uma delas é a definição de uma "linha" sendo uma sequência de zero ou mais não-caracteres mais um caractere de nova linha de terminação.

Portanto, para que a última linha seja reconhecida como uma "linha" real, ela deve ter um caractere de nova linha de terminação.

Isso é importante se você depender de ferramentas do sistema operacional para dizer que a contagem de linhas ou a divisão / ajuda analisam seu arquivo. Dado o PHP é uma linguagem de script, é totalmente possível, especialmente em seus primeiros dias ou até agora (eu não tenho idéia / postulando) que tinha dependências do sistema operacional como esse.

Na realidade, a maioria dos sistemas operacionais não é totalmente compatível com POSIX e os seres humanos não são tão parecidos com máquinas ou mesmo se preocupando com a terminação de novas linhas. Então, para a maioria das coisas, é uma miscelânea de tudo, ou se importar com isso, avisar ou apenas ir aquele último pedaço de texto é realmente uma linha, então inclua-o.

    
por 15.11.2017 / 14:26