Tenho problemas para entender um comportamento estranho: o vi parece adicionar uma nova linha (ASCII: LF, pois é um sistema Unix ( AIX )) no final do arquivo, quando NÃO o digitei especificamente.
Eu edito o arquivo como tal no vi (tomando cuidado para não inserir uma nova linha no final):
# vi foo ## Which I will finish on the char "9" and not input a last newline, then `:wq`
123456789
123456789
123456789
123456789
~
~
## When I save, the cursor is just above the last "9", and no newline was added.
Espero que o vi salve-o "como está", para ter 39 bytes: 10 caracteres ASCII em cada uma das três primeiras linhas (números 1 a 9, seguidos por uma nova linha (LF no meu sistema)) e apenas 9 nos últimos linha (caracteres de 1 a 9, sem nova linha / LF).
Mas parece que quando eu o salvo são 40 bytes (em vez de 39), e od mostra um LF final :
# wc foo
4 4 40 foo ## I expected 39 here! as I didn't add the last newline
# od -a toto
0000000 1 2 3 4 5 6 7 8 9 lf 1 2 3 4 5 6
0000020 7 8 9 lf 1 2 3 4 5 6 7 8 9 lf 1 2
0000040 3 4 5 6 7 8 9 lf
0000050
## An "lf" terminates the file?? Did vi add it silently?
Se eu criar o arquivo com um printf fazendo exatamente o que fiz no vi, ele funcionará conforme o esperado:
# ## I create a file with NO newline at the end:
# printf "123456789\n123456789\n123456789\n123456789" > foo2
# wc foo2 ## This one is as expected: 39 bytes, exactly as I was trying to do above with vi.
3 4 39 foo ## As expected, as I didn't add the last newline
## Note that for wc, there are only three lines!
## (So wc -l doesn't count lines; it counts the [newline] chars... Which is rather odd.)
# root@SPU0WMY1:~ ## od -a foo2
0000000 1 2 3 4 5 6 7 8 9 lf 1 2 3 4 5 6
0000020 7 8 9 lf 1 2 3 4 5 6 7 8 9 lf 1 2
0000040 3 4 5 6 7 8 9
0000047 ## As expected, no added LF.
Ambos os arquivos (foo (40 caracteres) e foo2 (39 caracteres) aparecem exatamente iguais se eu os reabrir com vi ...
E se eu abrir foo2 (39 caracteres, sem nova linha final) no vi e simplesmente não :wq
precisar editá-lo , ele diz que escreve 40 caracteres e o feed de linha aparece!
Não posso ter acesso a um vi mais recente (eu faço isso no AIX, vi (não no Vim ) versão 3.10, acho? (Sem "versão" ou outro meio de conhecê-lo)).
# strings /usr/bin/vi | grep -i 'version.*[0-9]'
@(#) Version 3.10
É normal que o vi (e talvez não na versão mais recente? Ou o Vim?) Adicione silenciosamente uma nova linha no final de um arquivo? (Eu pensei que o ~ indicava que a linha anterior NÃO terminava com uma nova linha.)
-
Edit: algumas atualizações adicionais e um pouco de resumo, com um grande agradecimento às respostas abaixo:
O vi adiciona silenciosamente uma nova linha à direita no momento em que grava um arquivo que não possui (a menos que o arquivo esteja vazio).
só o faz no momento da escrita! (ou seja, até você: w, você pode usar: e para verificar se o arquivo ainda está como você o abriu ... (ou seja: ele ainda mostra "filename" [A última linha não está completa] N line, caractere M). Quando você salva, uma nova linha é adicionada silenciosamente, sem um aviso específico (indica quantos bytes ela salva, mas na maioria dos casos não é suficiente para saber que uma nova linha foi adicionada) (obrigado a @jiliagre por falar comigo sobre o abrindo a mensagem vi, isso me ajudou a encontrar uma maneira de saber quando a mudança realmente ocorre)
Essa (correção silenciosa) é um comportamento POSIX ! (veja @ barefoot-io answer para referências)
vi
versão ou pelo menos uma pista sobre sua origem executando o:ve
comandoex
página do manual em que o:ver
comando normalmente está documentado.Respostas:
Esse é o
vi
comportamento esperado .Seu arquivo possui uma última linha incompleta, de maneira estrita (isto é, de acordo com o padrão POSIX), não é um arquivo de texto, mas um arquivo binário.
vi
que é um editor de arquivo de texto, não binário, corrige-o normalmente quando você o salva.Isso permite que outras ferramentas de arquivo de texto, como
wc
,sed
eo gosta de fornecer a saída esperada. Observe quevi
não há silêncio sobre o problema:Observe que, para obter algumas dicas sobre qual
vi
versão você está executando, você pode usar o:ve
comando Mostra aqui que estou usando um SVR4 herdado aqui, definitivamente nãovim
:Aparentemente, o seu está declarando:
Isso provavelmente significa que o AIX
vi
é baseado no código-fonte SVR3.De qualquer forma, esse comportamento e a
[Incomplete last line]
mensagem de aviso estão novi
código-fonte herdado de Bill Joy desde pelo menos 1979 e no AFAIK, retidos em todas as ramificações criadas a partir dos lançamentos de código-fonte do System V, a partir dos quais o Unix proprietário como o AIX foi construído.Cronologicamente falando, esse comportamento não é uma conseqüência da conformidade com o POSIX, mas mais uma consequência da decisão original de Bill Joy de ajudar os usuários a editar arquivos de texto falsos e, uma década depois, com a decisão do comitê do POSIX de manter essa tolerância.
Se você usar em
ed
vez devi
, notará que o primeiro é mais detalhado sobre o problema, pelo menos se vocêed
é do SVR3 ou de uma ramificação de origem mais recente:Observe também que um arquivo vazio é um arquivo de texto válido que contém zero linhas. Como não há uma linha não terminada para corrigir,
vi
não anexa uma nova linha ao salvar o arquivo.fonte
vi
assim como o OP, embora em um Unix diferente. Este não évim
ou outro clone. Resposta atualizada para esclarecer isso.vi
implementação. Possivelmente SVR3. Tem certeza de que não há[Incomplete last line]
mensagem quando você abre o arquivo?vi
implementação: www-01.ibm.com/support/docview.wss?uid=isg1IZ27694O POSIX requer esse comportamento, portanto não é incomum.
No manual do POSIX vi :
Seguindo a trilha para o manual POSIX ex :
A seção OUTPUT FILES do manual vi também redireciona para ex:
Um par de definições POSIX:
Essas definições no contexto desses trechos da página de manual significam que, enquanto uma implementação ex / vi em conformidade deve aceitar um arquivo de texto malformado, se a única deformidade desse arquivo for uma nova linha final ausente, ao gravar o buffer desse arquivo, o resultado deve ser um arquivo de texto válido.
Embora este post tenha feito referência à edição de 2013 do padrão POSIX, as estipulações relevantes também aparecem na edição de 1997 muito mais antiga .
Por fim, se você achar indesejável a nova linha de ex, sentir-se-á profundamente violado pelo intolerante ed da Sétima Edição UNIX (1979). Do manual :
fonte
ex
(não saiba o nome dele), acho que as especificações do POSIX são tão boas quanto se pode esperar. ;) Mais próximo da "fonte original" nesse ponto, mesmo que seja verdade que eles começaram como descrições mais ou menos da funcionalidade existente.ex
foi co-escrito por Bill Joy e Chuck Alley ( web.cecs.pdx.edu/~kirkenda/joy84.html .) Eu não questiono o POSIX especificações eo fato atuaisvi
lançamentos não segui-lo, eu só indicar o comportamento há muito tempo.Não recordo nenhum outro comportamento que uma nova linha seja adicionada no final de um arquivo (usando
vi
desde meados dos anos 80).O
~
indica que uma linha na tela que não é parte do texto, não que o arquivo não termina em uma nova linha. (Pode ser difícil rastrear erros se você colocar um~
na última linha de scripts de shell). Se você carregar um arquivo curto com uma nova linha no final, verá a~
si mesmo e negará que o seu pensamento indica um texto que não termina com a nova linha.fonte
ed
), você criaria linhas e as editaria, não acrescentando caracteres. Eu sempre pensei no vi como um editor orientado a linhas também. Mas eu entendo sua surpresa.O texto que carece indevidamente da execução de nova linha final em um
while
loop de shell faz com que a última linha seja descartada silenciosamente.Garantir que haja uma nova linha definitiva é o padrão correto, correto e adequado. A outra opção envolve conhecer e ter tempo para auditar todos os códigos de shell que tocam no texto sem a nova linha final ou correr o risco de perder a última linha do texto.
fonte