Diferencia en el espacio en blanco entre dos archivos en Linux

15

Tengo dos archivos que cuando comparo con diff muestran que cada línea ha cambiado. Cuando los comparo con diff -w(ignorando espacios en blanco) muestra los pocos cambios mínimos que espero.

Obviamente hay alguna diferencia entre los espacios en blanco en cada archivo, pero no sé qué son ni cómo encontrarlos. Intenté editar los archivos para asegurarme de que el espacio en blanco sea en realidad caracteres de espacio (en lugar de pestañas), pero no estoy seguro de qué más hacer.

He usado vim con :set list onpara confirmar que no había espacio final al final de las líneas.

También creo que cada archivo tiene terminadores de línea de Linux ya que vim no mostró ^Mel final de las líneas.

Romski
fuente
1
¿Ha verificado los espacios en blanco al final (al final de una línea)? Tal espacio será detectado por, diffpero muchos editores, de manera predeterminada, no lo hacen visible.
John1024
Buena sugerencia. Usé vim con ": set list on", esto mostró el "$" al final de la línea y no había espacio final. Actualizaré mi pregunta
Romski,
Si es vimusuario, ¿ha intentado usar vimdiff file1 file2para ver cuáles son las diferencias?
John1024
@ John1024 No tenía conocimiento de vimdiff, pero parece prometedor.
Agréguelo
1
Vim muestra ^ M solo cuando detecta mal la finalización de una línea Unix pero el archivo realmente tiene la finalización de la línea DOS. Por lo general, esto sucede si tiene una línea mixta que termina en un solo archivo, por ejemplo, aplicando un parche con una línea diferente que termina en el archivo original. Cuando vim detecta que la línea de DOS termina correctamente, no habría mostrado la ^ M.
Mentira Ryan

Respuestas:

7

Para los vimusuarios, hay una práctica utilidad para mostrar diferencias exactas entre archivos:

vimdiff file1 file2

Esto pondrá cada archivo en ventanas, uno al lado del otro, y las diferencias se resaltarán en color.

Algunos comandos útiles cuando en vimdiff

Mientras que en vimdiff, algunos comandos útiles son:

  • ]c: salta al siguiente cambio

  • [c: saltar al cambio anterior

  • ctrl-W ctrl-W: cambiar a otra ventana

  • zo: pliegues abiertos

  • zc: cerrar pliegues

Ejemplo

Aquí es un ejemplo de vimdiffen un xtermcomparan dos versiones de un cupsfichero de configuración:

ingrese la descripción de la imagen aquí

Puede ver que secciones largas de líneas idénticas se han colapsado. Se pueden abrir de nuevo con zo.

El esquema de color variará dependiendo de la configuración de su opción. En el ejemplo anterior, cuando aparece una línea en un archivo pero no en el otro, a esa línea se le asigna un fondo azul oscuro. En el otro archivo, las líneas que faltan se indican con líneas discontinuas. Cuando aparece una línea en ambos archivos pero tiene algunas diferencias, las partes sin cambios de las líneas tienen un fondo rosado y las partes cambiadas tienen un fondo rojo.

John1024
fuente
14

En FreeBSD o en la mayoría de los sistemas Linux, puede canalizar la salida de diff cat -v -e -tpara mostrar las diferencias de espacios en blanco.

diff file1 file2 | cat -vet

Las pestañas se mostrarán como ^I, $se mostrará un al final de cada línea para que pueda ver los espacios en blanco al final, y los caracteres no imprimibles se mostrarán como ^Xo M-X.

Si tiene coreutils de GNU (disponible en la mayoría de las distribuciones de Linux que no están ocupadas), esto se puede simplificar a

diff file1 file2 | cat -A

En sistemas busybox, use catv -vet.

Mark Plotnick
fuente
2

¿Se editó uno de los archivos en una máquina con Windows?

La terminación de línea estándar en Windows es CRLF, donde en Linux es simplemente LF (y en Mac solía ser CR, pero sospecho que ha cambiado desde OS X).

Pruebe wc -llos archivos y vea cuántas líneas, luego vea si la diferencia de tamaño es la misma que la cantidad de líneas (la última línea no puede terminar en un archivo).

poste de la cerca
fuente
Gracias por la rápida respuesta. Hacer un recuento de líneas muestra que un archivo tiene 5 líneas más (espero esto ya que hice modificaciones). Obtuve un archivo de una máquina Linux y el otro fue extraído de un repositorio de código en Linux. Creo que ver un archivo con terminadores de Windows en vim mostrará el último carácter como ^ M y ese no es el caso.
Romski
3
vim es lo suficientemente inteligente como para detectar automáticamente la terminación de la línea, consulte stackoverflow.com/questions/3852868 para obtener más detalles.
cercado
¡No estaba al tanto de eso! Volveré a verificar
Romski,
2

odpuede ayudar. El comando Volcado octal puede mostrar contenido en hexadecimal. Esto puede ayudarlo a ver qué bytes, incluidos los bytes nulos o los espacios en blanco inesperados, hay en un archivo. Las posibles causas comunes pueden ser LF vs CRLF, tabulaciones vs espacios, o ASCII vs Unicode (que a menudo puede tener un byte nulo antes de cada byte normalmente visible). od -x filenamedebería revelar cualquiera de esos patrones. Si desea una forma más elaborada de ver el archivo, cualquier "editor hexadecimal" puede funcionar bien. Lo bueno de esto odes que, al igual que el cutcomando, está integrado en muchos sistemas Unix. Entonces, a menudo, no es necesaria una instalación separada.

Si necesita que los archivos sean más similares, trpuede hacer algunos cambios y sedpuede hacer más. Probablemente comenzaría ls -lpor ver qué archivo es más grande, luego veré los bytes para ver qué se debe cambiar y luego cambiaré uno de los archivos para que parezcan más similares.

TOOGAM
fuente
1

Para averiguar dónde están los espacios en blanco y las pestañas reales, puede reemplazarlos usando, sedpor ejemplo:

$ cat file
  line 1
  line 2
    line 6
        line 7
$ sed 's/ /-/g; s/\t/<tab>/g' file
--line-1
--line-2
<tab>line-6
<tab><tab>line-7

Y ahora compara los dos archivos.

caos
fuente
Aún mejor, podría ejecutar ese filtro en la salida diff. O puede utilizar el filtro ya hechas en cat, como en superuser.com/a/913368/37154
clacke
0

El siguiente contenido se copió aquí de la sección de "preguntas" anterior, escrita por Romski.

Ambos vimdiffy diff file1 file2 | cat -Afueron muy útiles desde una perspectiva de herramientas.

Por último, encontré otro problema. Algunos de mis archivos fueron codificados con UTF-8 BOM. Esto fue resaltado usando diff file1 file2 | cat -A. Esto se manifestó como M-oM-;M-?al comienzo del archivo afectado:

$ diff file1 file2 | cat -A
< package com.mycompany;$
---$
> M-oM-;M-?package com.mycompany;$

Si bien hubo una serie de problemas, he enumerado un par de comandos a continuación para aquellos que necesitan limpiar sus archivos:

# recursively remove UTF8 BOM
find . -type f -exec sed -i -e '1s/^\xEF\xBB\xBF//' {} \;

# recursively replace CRLF with LF
find . -type f -print0 | xargs -0 dos2unix
Kevin Panko
fuente