Se eu tiver o seguinte texto:
foo
bar
Eu visualmente seleciono e copio.
O texto está agora armazenado no registro sem nome "
e aqui está o seu conteúdo (saída de :reg "
):
"" foo^Jbar^J
De acordo com este gráfico , parece ^J
ser a notação de sinal de intercalação para um avanço de linha.
Se eu quiser duplicar o registro sem nome no a
registro, digitando: :let @a = @"
Aqui está o conteúdo (saída de :reg a
):
"a foo^Jbar^J
Isso não mudou.
Se agora eu o duplicar no registro de pesquisa, digitando :let @/ = @"
, eis o conteúdo (saída de :reg /
):
"/ foo^@bar^@
De acordo com o gráfico anterior, parece ^@
ser a notação de sinal de intercalação para um caractere nulo.
Por que um feed de linha é automaticamente convertido em um caractere nulo no registro de pesquisa (mas não no a
registro)?
Se eu inserir o registro sem nome na linha de comando (ou dentro de uma pesquisa depois /
), digitando :<C-R>"
, aqui está o que é inserido:
:foo^Mbar^M
Mais uma vez, de acordo com o último gráfico, ^M
parece ser a notação de intercalação para um retorno de carro.
Por que um avanço de linha é automaticamente convertido em retorno de carro na linha de comando?
Editar :
Geralmente, você pode inserir um caractere de controle literal digitando:
<C-V><C-{character in caret notation}>
Por exemplo, você pode inserir um literal <C-R>
digitando <C-V><C-R>
.
Você pode fazer isso para aparentemente qualquer personagem de controle.
No entanto, notei que não consigo inserir um LF literal dentro de um buffer ou na linha de comando, porque se eu digitar: <C-V><C-J>
insere ^@
, um caractere nulo, em vez de ^J
.
É pelo mesmo motivo que um LF é convertido em NUL dentro do registro de pesquisa?
Edição 2 :
Em :h key-notation
, podemos ler o seguinte:
<Nul> zero CTRL-@ 0 (stored as 10) <Nul>
<NL> linefeed CTRL-J 10 (used for <Nul>)
A stored as 10
parte na primeira linha e used for <Nul>
na segunda linha pode indicar que há algum tipo de sobreposição entre um LF e um NUL, e que eles podem ser interpretados como a mesma coisa. Mas eles não podem ser a mesma coisa, porque depois de executar o comando anterior :let @/ = @"
, se eu digitar n
no modo normal para chegar à próxima ocorrência das 2 linhas foo
e bar
, em vez de obter uma correspondência positiva, tenho a seguinte mensagem de erro:
E486: Pattern not found: foo^@bar^@
Além desse link, parece explicar que um NUL denota o final de uma string, enquanto um LF denota o final de uma linha em um arquivo de texto.
E se um NUL é stored as 10
como a ajuda diz, que é o mesmo código que para um LF, como o Vim é capaz de fazer a diferença entre os 2?
Edição 3 :
Talvez um LF e um NUL sejam codificados com o mesmo código decimal 10
, como diz a ajuda. E o Vim faz a diferença entre os 2, graças ao contexto. Se encontrar um caractere cujo código decimal esteja 10
em um buffer ou em qualquer registro, exceto os registros de pesquisa e comando, ele o interpretará como um LF.
Porém, no registro de pesquisa ( :reg /
), ele é interpretado como um NUL porque, no contexto de uma pesquisa, o Vim procura apenas uma sequência em que o conceito de end of line in a file
não faz sentido porque uma sequência não é um arquivo (o que é estranho, pois você pode ainda usa o átomo \n
em um padrão pesquisado, mas talvez isso seja apenas um recurso do mecanismo de expressão regular?). Portanto, ele interpreta automaticamente 10
como um NUL porque é o conceito mais próximo ( end of string
≈ end of line
).
E da mesma maneira, na linha de comando / command register ( :reg :
) ele interpreta o código 10
como um CR, porque o conceito de end of line in a file
não faz sentido aqui. O conceito mais próximo é end of command
que o Vim interpreta 10
como um CR, porque bater Enter
é a maneira de terminar / executar um comando e um CR é o mesmo que bater Enter
, pois quando você insere um literal com <C-V><Enter>
, ^M
é exibido.
Talvez a interpretação do personagem cujo código seja 10
alterado de acordo com o contexto:
- fim de linha em um buffer (
^J
) - fim da string em uma pesquisa (
^@
) - fim do comando na linha de comando (
^M
)
fonte
NULL
caracteres inesperados é causada pela função C subjacente que está manipulando as seqüências de caracteres. Esta explicação de como C processa seqüências de caracteres às quais você vinculou explica que internamente C delimita seqüências de caracteres com aNULL
.NULL
s ocorrem raramente no texto, o que o torna um bom caractere para esse fim. Uma consequência disto é que, se o programa de C (VIM) tentou transmitir uma "esvaziar" cadeia numa função interna CsomeFunction(arg1, "")
onde arg 2 estava,""
ou seja, "o item entre aspas, que literalmente não é nada - um" vazio ". um NULL pode aparecer, porque foi" adicionado "pela implementação C subjacente, pois delimitou a string. Não sei como você iria verificar para isso - mas ele vem à mente como uma possível causa.\r
e a\n
diferença em:substitute
.Respostas:
Primeiro, obrigado por este post muito abrangente e atencioso.
Após alguns testes, cheguei a esta conclusão:
Os caracteres de controle são exibidos usando a notação de sinal de intercalação:
^M
para<CR>
(retorno de carro) e^J
para<LF>
(avanço de linha). Nos buffers,<EOL>
(fim de linha) são exibidos como novas linhas da tela e são inseridos com a tecla Enter.<EOL>
dependem do formato do buffer de arquivo:<EOL> = <CR>|<LF>|<CR><LF>
paramac|unix|dos
, respectivamente.Ao editar um buffer, o formato do arquivo é sempre definido. Para alterar o formato do arquivo de um buffer aberto, você pode usar o seguinte comando que converte
<EOL>
:Além de converter
<EOL>
, esse comando é convertido<LF>
em<CR>
quando o formato do arquivo é alterado demac
paraunix|dos
e, inversamente,<CR>
em<LF>
quando o formato do arquivo é alterado deunix|dos
paramac
. Para ver os bytes reais do buffer, você pode usar o seguinte comando que transforma a representação textual do buffer em sua representação hexadecimal usando o conveniente editor hexadecimal xxd:Nos registradores (mostrados com o comando
:reg[isters]
ou:di[splay]
),<EOL>
sempre são exibidos como^J
(mas nem todos^J
são<EOL>
), independentemente do formato do arquivo do buffer. No entanto,<EOL>
são armazenados como deveriam. Para poder distinguir visualmente real^J
(ou seja<LF>
) dos outros^J
(ou seja<EOL>
) nos registros, você pode usar o seguinte comando que exibe os valores hexadecimais em vez da notação de sinal de intercalação dos caracteres de controle diferentes de<EOL>
:Nos padrões de pesquisa e cadeias de substituição:
Em toda parte:
Isso mostra que, quando o formato do arquivo é
dos
, é impossível inserir<LF>
, pois<EOL> = <CR><LF>
e<C-V><C-M>|<C-V><EOL> = <CR>
.Nas cadeias de substituição:
nova linha diferente de
<EOL>
são interpretadas como<EOL>
;<EOL>
são interpretados como<NUL>
.Portanto, de acordo com 4.,
:%s[ubstitute]/\r/\r/g
substitui todas as novas linhas diferentes do<EOL>
buffer por<EOL>
, enquanto:%s[ubstitute]/\n/\n/g
substitui todas<EOL>
as novas linhas do buffer por<NUL>
.No registro de pesquisa
/
e registro de comando:
,<EOL>
são convertidos emnova linha diferente de
<EOL>
quando inserida de um registro com/<C-R>{register}
ou:<C-R>{register}
respectivamente;<NUL>
quando inserido a partir de um registro com:let @/=@{register}
ou:let @:=@{register}
respectivamente.Nos buffers, uma nova linha diferente de
<EOL>
é convertida para<EOL>
quando inserida de um registro usandoi<C-R>{register}
.Antes de copiar
<LF>
do registro não nomeado"
para outros registros, é necessário inserir<LF>
e colocá-lo no registro"
. Se o formato do arquivo forunix
, você poderá fazer isso usandoyy
uma linha vazia; se o formato do arquivo formac
, você poderá fazer isso usandoi<C-V><C-M><Esc>yl
; se o formato do arquivo fordos
, você não poderá inserir<LF>
(cf. 5.).Agora sua declaração está parcialmente errada, pois
você não usa o mesmo método para copiar
<LF>
do registro"
para o registro de pesquisa/
e comando:
. Você usa:let @/=@"
para copiar para o registro/
e:<C-R>"
para copiar para o registro:
. Usar/<C-R>"
e:<C-R>"
respectivamente fornecerá o mesmo resultado (<CR>
) nos dois casos;as conversões
<LF>
que ocorrem com seus dois métodos diferentes de cópia ocorrem apenas quando o formato do arquivo éunix
. Se formac
, não<LF>
é convertido quando copiado para o registro ou o registro , e se for, você não pode nem inserir ./
:
dos
<LF>
A afirmação correta é dada por 7. Mas eu realmente não sei as razões por trás disso.
fonte