Pregunta ¿Cómo puedo obtener diff para mostrar solo las líneas agregadas y eliminadas? Si diff no puede hacerlo, ¿qué herramienta puede?


¿Cómo puedo obtener diff para mostrar solo las líneas agregadas y eliminadas? Si diff no puede hacerlo, ¿qué herramienta puede?


60
2017-09-25 12:47


origen


Necesita definir mejor lo que quiere decir con agregado y eliminado. Específicamente, ¿puede una línea cambiar? Si es así, ¿cómo quiere que se maneje una línea cambiada? Si está realizando una comprobación estrictamente orientada a la línea, un cambio de línea es idéntico a la línea anterior que se está eliminando y la nueva línea que se está agregando. Por ejemplo, ¿cómo debería manejar una línea que se divide en dos? Como dos líneas cambiadas 1? 2 lineas cambiadas? 1 línea eliminada y 2 líneas agregadas? A menos que pueda garantizar que las líneas nunca cambien, solo se agreguen y eliminen, creo que está condenado a fallar sin mejores definiciones. - Christopher Cashell
Encuentro la pregunta bastante confusa. Pero al menos una interpretación de la pregunta podría ser respondida con diff A B | grep '^[<>]' - kasperd
Usted puede estar buscando comm. - Jenny D
@ChristopherCashell, Él quiere decir ignorar el orden; Un problema típicamente común. Por lo general, esto se hace primero clasificando los segmentos (líneas) en cada lado antes de hacer una diferencia típica. - Pacerier
@Pacerier, ¿estás seguro de eso? ¿O estás adivinando? En la pregunta no se menciona ni se insinúa nada sobre la ordenación o el orden de búsqueda. Tal como está, la pregunta no es clara y podría interpretarse de muchas maneras diferentes. Sin saber sin lugar a duda lo que está preguntando, estamos haciendo suposiciones y ofreciendo soluciones que pueden o no resolver el problema real. Además, el comentario del póster original sobre una de las respuestas sugiere que esto es no relacionado con la clasificación. Tiene que ver con el significado de "agregado y eliminado" frente a "cambiado". - Christopher Cashell


Respuestas:


Otra forma de verlo:

Mostrar líneas que solo existen en el archivo a: (es decir, lo que se eliminó de a)

comm -23 a b

Mostrar líneas que solo existen en el archivo b: (es decir, lo que se agregó a b)

comm -13 a b

Mostrar líneas que solo existen en un archivo u otro: (pero no ambos)

comm -3 a b | sed 's/^\t//'

(Advertencia: Si el archivo a tiene líneas que comienzan con TAB, se eliminará (la primera TAB) de la salida.)

NOTA: Ambos archivos deben ordenarse para que "comm" funcione correctamente. Si no están ya ordenados, deberías ordenarlos:

sort <a >a.sorted
sort <b >b.sorted
comm -12 a.sorted b.sorted

Si los archivos son extremadamente largos, esto puede ser una carga, ya que requiere una copia adicional y, por lo tanto, el doble de espacio en disco.


73
2017-09-25 18:11



solo quería agregar que ambos archivos deben ordenarse (distingue entre mayúsculas y minúsculas) para que esta solución produzca resultados correctos - marmor
En conchas suficientemente modernas, puede ordenar en línea con algo como comm -12 <(sort a) <(sort b) - Joshua Huber


comm Podrías hacer lo que quieras. Desde su página de manual:

DESCRIPCIÓN

Compare los archivos ordenados FILE1 y FILE2 línea por línea.

Sin opciones, producir salida de tres columnas. Columna uno   contiene líneas únicas para ARCHIVO1, columna   dos contiene líneas únicas para FILE2,   y la columna tres contiene líneas comunes   a ambos archivos.

Estas columnas son supresibles con -1, -2 y -3 respectivamente.

Ejemplo:

[root@dev ~]# cat a
common
shared
unique

[root@dev ~]# cat b
common
individual
shared

[root@dev ~]# comm -3 a b
    individual
unique

Y si solo quieres las líneas únicas y no te importa en qué archivo están:

[root@dev ~]# comm -3 a b | sed 's/^\t//'
individual
unique

Como dice la página de manual, los archivos deben ordenarse de antemano.


12
2017-09-25 14:27





Para mostrar adiciones y eliminaciones sin contexto, números de línea, +, -, <,>! etc, puede utilizar dif como este:

diff --changed-group-format='%<%>' --unchanged-group-format='' a.txt b.txt 

Por ejemplo, dados dos archivos:

a.txt

Common
Common
A-ONLY
Common

b.txt

Common
B-ONLY
Common
Common

El siguiente comando mostrará las líneas eliminadas de a o agregadas a b:

diff --changed-group-format='%<%>' --unchanged-group-format='' a.txt b.txt 

salida:

B-ONLY
A-ONLY

Este comando ligeramente diferente mostrará las líneas eliminadas de a.txt:

diff --changed-group-format='%<' --unchanged-group-format='' a.txt b.txt 

salida:

A-ONLY

Finalmente, este comando mostrará las líneas agregadas a a.txt.

diff --changed-group-format='%>' --unchanged-group-format='' a.txt b.txt 

salida

B-ONLY

8
2018-01-05 06:41





Eso es lo que hace diff de forma predeterminada ... ¿Quizás necesite agregar algunas banderas para ignorar los espacios en blanco?

diff -b -B

Debe ignorar las líneas en blanco y diferentes números de espacios.


2
2017-09-25 13:26



No, también muestra líneas CAMBIADAS (líneas que tienen un carácter o cuatro diferentes). Quiero líneas que solo existen en izquierda o derecha. - C. Ross
Podría argumentar que las diferentes versiones de un archivo CAMBIADO existen solo en la izquierda o la derecha. - markdrayton
No hay forma de que diff (o cualquier otra herramienta) pueda decir de manera confiable qué es un cambio, y qué es una línea eliminada que está siendo reemplazada por una nueva línea. - Cian
Técnicamente, diff trata una línea "modificada" como si la línea original se hubiera eliminado y se hubiera agregado una nueva ... así que técnicamente muestra que solo se agregaron y eliminaron líneas. - KFro


No, diff en realidad no muestra las diferencias entre dos archivos en la forma en que uno podría pensar. Produce una secuencia de comandos de edición para una herramienta como patch para utilizar para cambiar un archivo en otro.

La dificultad de cualquier intento de hacer lo que está buscando es cómo definir qué constituye una línea que ha cambiado en comparación con una eliminada seguida de una agregada. También qué hacer cuando se agregan, eliminan y cambian líneas adyacentes entre sí.


2
2017-09-25 15:59



Mis pensamientos exactamente. ¿Qué porcentaje de caracteres en una línea tiene que cambiar para considerarlo uno nuevo en lugar de una modificación del original? Técnicamente, incluso si tiene un carácter en común, podría considerarlo un "cambio" en lugar de una eliminación e inserción. - Kamil Kisiel
Hace mucho tiempo que no miro el diff fuentes, pero me parece recordar todo tipo de giros para hacer un seguimiento de dónde coinciden dos archivos para estar sincronizados y creo que hay un umbral para rendirse según lo alejadas que estén las líneas. Pero no recuerdo ninguna coincidencia dentro de la línea a excepción de (opcionalmente) espacio en blanco colapsado o caso de ignorar. O (quizás) palabras a ese efecto. En cualquier caso, se trata de patch y "vgrep" solo viene para el paseo. Tal vez. El martes. - Dennis Williamson


Las herramientas de comparación visual se ajustan a dos archivos para que un segmento con el mismo número de líneas pero contenido diferente se considere un segmento modificado. Las líneas completamente nuevas entre segmentos coincidentes se consideran segmentos agregados.

Así es como sdiff La herramienta de línea de comandos funciona, que muestra una comparación lado a lado de dos archivos en un terminal. Las líneas modificadas están separadas por | personaje. Si solo existe una línea en el archivo A, <se utiliza como carácter separador. Si solo existe una línea en el archivo B,> se utiliza como separador. Si no tiene los caracteres <y> en los archivos, puede usar esto para mostrar solo las líneas agregadas:

sdiff A B | grep '[<>]'

2
2017-10-17 14:34





Gracias, senarvi, su solución (no votada) en realidad me dio EXACTAMENTE lo que quería después de buscar por edades en una tonelada de páginas.

Usando su respuesta, esto es lo que se me ocurrió para obtener la lista de cosas cambiadas / agregadas / eliminadas. El ejemplo utiliza 2 versiones del archivo / etc / passwd e imprime el nombre de usuario para los registros relevantes.

#!/bin/bash
sdiff passwd1 passwd2 | grep '[|]' | awk -F: '{print "changed: " $1}'
sdiff passwd1 passwd2 | grep '[<]' | awk -F: '{print "deleted: " $1}'
sdiff passwd1 passwd2 | grep '[>]' | awk -F\> '{print $2}' | awk -F: '{print "added: " $1}'

2
2017-11-18 12:05



Tenga en cuenta que debido a que la diferencia entre "una línea se ha modificado" y "una línea se ha eliminado y otro la línea se ha agregado por debajo o por encima de ella "es semántica. Una herramienta de diferenciación basada en texto genérico no puede separar esos casos. Como resultado, su respuesta basada en sdiff no puede funcionar de manera confiable para todos los casos. - Mikko Rantalainen


Archivo1:

text670_1
text067_1
text067_2

Archivo2:

text04_1
text04_2
text05_1
text05_2
text067_1
text067_2
text1000_1

Utilizar:

diff -y file1 file2

Esto muestra dos columnas para archivos de repectives.

Salida:

text670_1                           
                                  > text04_1
                                  > text04_2
                                  > text05_1
                                  > text05_2
text067_1                           text67_1
text067_2                           text67_2
                                  > text1000_1

-1
2017-10-17 18:42