Tengo problemas para entender un comportamiento extraño: vi parece agregar una nueva línea (ASCII: LF, ya que es un sistema Unix ( AIX )) al final del archivo, cuando NO lo escribí específicamente.
Edito el archivo como tal en vi (teniendo cuidado de no ingresar una nueva línea al 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 vi lo guarde "como está", para tener 39 bytes: 10 caracteres ASCII en cada una de las tres primeras líneas (números 1 a 9, seguidos de una nueva línea (LF en mi sistema)) y solo 9 en la última línea (caracteres 1 a 9, sin línea nueva terminada / LF).
Pero aparece cuando lo guardo es de 40 bytes (en lugar de 39), y od muestra un 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?
Si creo el archivo con un printf haciendo exactamente lo que hice dentro de vi, funciona como se esperaba:
# ## 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 archivos (foo (40 caracteres) y foo2 (39 caracteres) aparecen exactamente iguales si los vuelvo a abrir con vi ...
Y si abro foo2 (39 caracteres, sin nueva línea de terminación) en vi y simplemente lo hago :wq
sin editarlo , dice que escribe 40 caracteres, ¡y aparece el salto de línea!
No puedo tener acceso a un vi más reciente (lo hago en AIX, vi (no en Vim ) versión 3.10, creo? (No "versión" u otro medio para saberlo)).
# strings /usr/bin/vi | grep -i 'version.*[0-9]'
@(#) Version 3.10
¿Es normal que vi (y tal vez no en una versión más reciente o Vim) agregue en silencio una nueva línea al final de un archivo? (Pensé que ~ indicaba que la línea anterior NO terminaba con una nueva línea).
-
Editar: algunas actualizaciones adicionales y un poco de resumen, con un gran agradecimiento a las respuestas a continuación:
vi agrega silenciosamente una nueva línea final en el momento en que escribe un archivo que le faltaba (a menos que el archivo esté vacío).
¡solo lo hace al momento de escribir! (es decir, hasta que: w, puede usar: e para verificar que el archivo todavía está tal como lo abrió ... (es decir: todavía muestra "nombre de archivo" [Última línea no está completa] Línea N, carácter M). Cuando guarda, se agrega una nueva línea de forma silenciosa, sin una advertencia específica (dice cuántos bytes guarda, pero en la mayoría de los casos esto no es suficiente para saber que se agregó una nueva línea) (gracias a @jiliagre por hablar conmigo sobre el abriendo el mensaje vi, me ayudó a encontrar una manera de saber cuándo ocurre realmente el cambio)
¡Esta (corrección silenciosa) es un comportamiento POSIX ! (ver la respuesta @ barefoot-io para referencias)
vi
versión o al menos una pista sobre su origen ejecutando el:ve
comando.ex
página del manual donde:ver
normalmente se documenta el comando.Respuestas:
Este es el
vi
comportamiento esperado .Su archivo tiene una última línea incompleta, por lo que, estrictamente hablando (es decir, de acuerdo con el estándar POSIX), no es un archivo de texto sino un archivo binario.
vi
que es un editor de archivos de texto, no binario, lo arregla con gracia cuando lo guarda.Esto permite que otras herramientas de archivos de texto, como Me gusta
wc
,sed
proporcionen el resultado esperado. Tenga en cuenta quevi
no es silencioso sobre el problema:Tenga en cuenta que para obtener algunas pistas sobre la
vi
versión que está ejecutando, puede usar el:ve
comando. Aquí se muestra que estoy usando un SVR4 heredado, definitivamente novim
:Aparentemente, el tuyo dice:
Eso probablemente significa que AIX
vi
se basa en el código fuente SVR3.En cualquier caso, este comportamiento y el
[Incomplete last line]
mensaje de advertencia han estado en elvi
código fuente heredado de Bill Joy desde al menos 1979 y AFAIK, retenido en todas las ramas creadas a partir de las versiones del código fuente del Sistema V, a partir de las cuales se construyeron Unix como AIX.Cronológicamente hablando, este comportamiento no es consecuencia de la conformidad con POSIX, sino más bien una consecuencia de la decisión original de Bill Joy de ayudar a los usuarios a editar archivos de texto falsos, y luego, una década después, la decisión del comité POSIX de mantener esta tolerancia.
Si usa en
ed
lugar devi
, notará que el primero es más detallado sobre el problema, al menos sied
es de SVR3 o de una rama fuente más nueva:Tenga en cuenta también que un archivo vacío es un archivo de texto válido que contiene cero líneas. Como no hay una línea sin terminar que corregir,
vi
no agrega una nueva línea al guardar el archivo.fuente
vi
al igual que el OP, aunque en un Unix diferente. Este no esvim
ni otro clon. Respuesta actualizada para aclarar esto.vi
implementación. Posiblemente SVR3. ¿Estás seguro de que no hay ningún[Incomplete last line]
mensaje cuando abres el archivo?vi
implementación de AIX : www-01.ibm.com/support/docview.wss?uid=isg1IZ27694POSIX requiere este comportamiento, por lo que no es de ninguna manera inusual.
Del manual POSIX vi :
Siguiendo el camino hacia el manual POSIX ex :
La sección ARCHIVOS DE SALIDA del manual vi también redirige a ex:
Un par de definiciones POSIX:
Estas definiciones en el contexto de estos extractos de página del manual significan que si bien una implementación ex / vi conforme debe aceptar un archivo de texto con formato incorrecto si la única deformidad de ese archivo es una nueva línea final ausente, al escribir el búfer de ese archivo, el resultado debe ser un archivo de texto válido.
Si bien esta publicación hace referencia a la edición 2013 del estándar POSIX, las estipulaciones relevantes también aparecen en la edición mucho más antigua de 1997 .
Por último, si encuentra que la apariencia de línea nueva de su ex no es bienvenida, se sentirá profundamente violado por la edición intolerante de UNIX (1979) de la Séptima Edición. Del manual :
fuente
ex
(no sé su nombre), creo que las especificaciones POSIX son tan buenas como se puede esperar. ;) Más cerca de la "fuente original" en este punto, aunque es cierto que comenzaron como más o menos descripciones de la funcionalidad existente.ex
fue co-escrito por Bill Joy y Chuck Alley ( web.cecs.pdx.edu/~kirkenda/joy84.html .) No cuestiono las especificaciones POSIX y el hecho de que lasvi
versiones actuales lo siguen, solo declaro el comportamiento mucho tiempo lo precede.No recuerdo ningún otro comportamiento que se agregue una nueva línea al final de un archivo (
vi
desde mediados de los 80).El
~
indica que una línea en la pantalla que no es parte del texto, no que el archivo no termine en una nueva línea. (Puede ser difícil rastrear errores si coloca un~
en la última línea de scripts de shell). Si carga un archivo corto con una nueva línea al final, lo verá~
usted mismo y refutará que su pensamiento indica que el texto no termina con una nueva línea.fuente
ed
) crearía líneas y las editaría, no agregando caracteres. Siempre pensé en vi como un editor orientado a líneas también. Pero entiendo tu sorpresa.El texto que carece incorrectamente de la última línea nueva ejecutada a través de un
while
bucle de shell da como resultado que la última línea se descarte silenciosamente.Asegurarse de que haya una nueva línea definitiva es el valor predeterminado correcto, correcto y correcto. La otra opción implica conocer y tener tiempo para auditar todo el código de shell que toca el texto que carece de la nueva línea final, o arriesgarse a perder la última línea del texto.
fuente