Si tengo el siguiente texto:
foo
bar
Lo selecciono visualmente y lo copio.
El texto ahora se almacena en el registro sin nombre "
y aquí está su contenido (salida de :reg "
):
"" foo^Jbar^J
Según este gráfico , parece ^J
ser la notación de intercalación para un avance de línea.
Si quiero duplicar el registro sin nombre en el a
registro escribiendo: :let @a = @"
Aquí está su contenido (salida de :reg a
):
"a foo^Jbar^J
No ha cambiado.
Si ahora lo duplico en el registro de búsqueda escribiendo :let @/ = @"
, aquí está su contenido (salida de :reg /
):
"/ foo^@bar^@
Según el gráfico anterior, parece ^@
ser la notación de intercalación para un carácter nulo.
¿Por qué un salto de línea se convierte automáticamente en un carácter nulo dentro del registro de búsqueda (pero no en el a
registro)?
Si inserto el registro sin nombre en la línea de comando (o dentro de una búsqueda después /
), al escribir :<C-R>"
, esto es lo que se inserta:
:foo^Mbar^M
Una vez más, según el último cuadro, ^M
parece ser la notación de intercalación para un retorno de carro.
¿Por qué un salto de línea se convierte automáticamente en un retorno de carro en la línea de comando?
Editar :
Por lo general, puede insertar un carácter de control literal escribiendo:
<C-V><C-{character in caret notation}>
Por ejemplo, puede insertar un literal <C-R>
escribiendo <C-V><C-R>
.
Puedes hacerlo por aparentemente cualquier personaje de control.
Sin embargo, me di cuenta de que no puedo insertar un LF literal dentro de un búfer o en la línea de comando, porque si escribo: <C-V><C-J>
inserta ^@
un carácter nulo en lugar de ^J
.
¿Es por la misma razón que un LF se convierte en NUL dentro del registro de búsqueda?
Edición 2 :
En :h key-notation
, podemos leer esto:
<Nul> zero CTRL-@ 0 (stored as 10) <Nul>
<NL> linefeed CTRL-J 10 (used for <Nul>)
La stored as 10
parte en la primera línea y used for <Nul>
en la segunda línea podría indicar que hay algún tipo de superposición entre un LF y un NUL, y que podrían interpretarse como la misma cosa. Pero no pueden ser lo mismo, porque después de ejecutar el comando anterior :let @/ = @"
, si escribo n
en modo normal para llegar a la siguiente aparición de las 2 líneas foo
y bar
, en lugar de obtener una coincidencia positiva, tengo el siguiente mensaje de error:
E486: Pattern not found: foo^@bar^@
Además, este enlace parece explicar que un NUL denota el final de una cadena, mientras que un LF denota el final de una línea en un archivo de texto.
Y si un NUL es stored as 10
como dice la ayuda, que es el mismo código que para un LF, ¿cómo puede Vim hacer la diferencia entre los 2?
Edición 3 :
Tal vez un LF y un NUL están codificados con el mismo código decimal 10
, como dice la ayuda. Y Vim marca la diferencia entre los 2 gracias al contexto. Si encuentra un carácter cuyo código decimal está 10
en un búfer o en cualquier registro, excepto los registros de búsqueda y comando, lo interpreta como un LF.
Pero en el registro de búsqueda ( :reg /
) lo interpreta como un NUL porque en el contexto de una búsqueda, Vim solo busca una cadena donde el concepto de end of line in a file
no tiene sentido porque una cadena no es un archivo (lo cual es extraño ya que puede todavía usa el átomo \n
en un patrón buscado, pero ¿tal vez eso sea solo una característica del motor de expresiones regulares?). Por lo tanto, se interpreta automáticamente 10
como un NUL porque es el concepto más cercano ( end of string
≈ end of line
).
Y de la misma manera, en la línea de comando / registro de comando ( :reg :
) interpreta el código 10
como un CR, porque el concepto de end of line in a file
no tiene sentido aquí. El concepto más cercano es end of command
que Vim interpreta 10
como un CR, porque golpear Enter
es la forma de finalizar / ejecutar un comando y un CR es lo mismo que golpear Enter
, ya que cuando inserta uno literal con <C-V><Enter>
, ^M
se muestra.
Tal vez la interpretación del personaje cuyo código es 10
cambia según el contexto:
- fin de línea en un buffer (
^J
) - fin de cadena en una búsqueda (
^@
) - fin del comando en la línea de comando (
^M
)
fuente
NULL
caracteres inesperados es causada por la función C subyacente que maneja las cadenas. Esta explicación de cómo C procesa las cadenas a las que se vinculó explica que internamente C delimita las cadenas con aNULL
.NULL
s ocurren raramente en el texto lo suficiente como para que sea un buen personaje para este propósito. Una consecuencia de esto es que si el programa C (vim) intentó pasar una cadena "vacía" a una función interna CsomeFunction(arg1, "")
donde arg 2 era,""
es decir, "el elemento entre las comillas, que literalmente no es nada: un" vacío ". Puede aparecer un NULL, porque fue" agregado "por la implementación subyacente de C ya que delimitó la cadena. No sé cómo le gustaría comprobar esto - pero viene a la mente como una posible causa.\r
y la\n
diferencia en:substitute
.Respuestas:
Primero, gracias por esta publicación tan completa y reflexiva.
Después de algunas pruebas, he llegado a esta conclusión:
Los caracteres de control se muestran utilizando la notación de intercalación:
^M
para<CR>
(retorno de carro) y^J
para<LF>
(avance de línea). En los buffers,<EOL>
(fin de línea) se muestran como nuevas líneas de pantalla y se ingresan con la tecla Intro.<EOL>
dependerá del formato de archivo del búfer:<EOL> = <CR>|<LF>|<CR><LF>
paramac|unix|dos
respectivamente.Al editar un búfer, el formato del archivo siempre se establece. Para cambiar el formato de archivo de un búfer abierto, puede usar el siguiente comando que convierte
<EOL>
:Además de la conversión
<EOL>
, este comando convierte<LF>
a<CR>
cuando se cambia el formato de archivo demac
aunix|dos
y, por el contrario,<CR>
a<LF>
cuando se cambia el formato de archivo deunix|dos
amac
. Para ver los bytes reales del búfer, puede usar el siguiente comando que transforma la representación textual del búfer en su representación hexadecimal usando el conveniente editor hexadecimal xxd:En registros (mostrado con el comando
:reg[isters]
o:di[splay]
),<EOL>
siempre se visualiza como^J
(pero no todos^J
son<EOL>
), independientemente del formato de archivo de la memoria intermedia. Sin embargo,<EOL>
se almacenan como deberían. Para poder distinguir visualmente real^J
(es decir<LF>
) de los otros^J
(es decir<EOL>
) en los registros, puede usar el siguiente comando que muestra los valores hexadecimales en lugar de la notación de caracteres de control diferentes de<EOL>
:En patrones de búsqueda y cadenas de sustitución:
En todas partes:
Esto muestra que cuando el formato de archivo es
dos
, es imposible ingresar<LF>
, ya que<EOL> = <CR><LF>
y<C-V><C-M>|<C-V><EOL> = <CR>
.En cadenas de sustitución:
nueva línea diferente de
<EOL>
se interpretan como<EOL>
;<EOL>
son interpretados como<NUL>
.Entonces, de acuerdo con 4.,
:%s[ubstitute]/\r/\r/g
reemplaza cada nueva línea diferente de<EOL>
en el búfer con<EOL>
, mientras que:%s[ubstitute]/\n/\n/g
reemplaza cada<EOL>
en el búfer con<NUL>
.En el registro de búsqueda
/
y el registro de comando:
,<EOL>
se convierten anueva línea diferente de
<EOL>
cuando se inserta desde un registro con/<C-R>{register}
o:<C-R>{register}
respectivamente;<NUL>
cuando se inserta desde un registro con:let @/=@{register}
o:let @:=@{register}
respectivamente.En tampones, salto de línea diferente de
<EOL>
se convierte a<EOL>
cuando se inserta desde un registro utilizandoi<C-R>{register}
.Antes de copiar
<LF>
desde el registro sin nombre"
a otros registros, debe ingresarlo<LF>
y colocarlo en el registro"
. Si el formato del archivo esunix
, puede hacerlo utilizandoyy
una línea vacía; si el formato del archivo esmac
, puede hacerlo usandoi<C-V><C-M><Esc>yl
; si el formato del archivo esdos
, no puede ingresar<LF>
(ver 5.).Ahora su declaración es parcialmente incorrecta, ya que
no utiliza el mismo método para copiar
<LF>
desde el registro"
al registro de búsqueda/
y al registro de comandos:
. Se utiliza:let @/=@"
para copiar en el registro/
y:<C-R>"
para copiar en el registro:
. Usar/<C-R>"
y:<C-R>"
respectivamente le dará el mismo resultado (<CR>
) en ambos casos;las conversiones de
<LF>
que tienen lugar con sus dos diferentes métodos de copia ocurren solamente cuando el formato de archivo esunix
. Si se tratamac
,<LF>
es no convertidos cuando se copian en el registro/
o en el registro:
, y si esdos
que no se puede ni siquiera de entrada<LF>
.La declaración correcta viene dada por 7. Pero realmente no sé las razones detrás de esto.
fuente