He leído sobre diff y patch pero no puedo entender cómo aplicar lo que necesito. Supongo que es bastante simple, así que para mostrar mi problema, tome estos dos archivos:
a.xml
<resources>
<color name="same_in_b">#AAABBB</color>
<color name="not_in_b">#AAAAAA</color>
<color name="in_b_but_different_val">#AAAAAA</color>
<color name="not_in_b_too">#AAAAAA</color>
</resources>
b.xml
<resources>
<color name="same_in_b">#AAABBB</color>
<color name="in_b_but_different_val">#BBBBBB</color>
<color name="not_in_a">#AAAAAA</color>
</resources>
Quiero tener una salida, que se ve así (el orden no importa):
<resources>
<color name="same_in_b">#AAABBB</color>
<color name="not_in_b">#AAAAAA</color>
<color name="in_b_but_different_val">#BBBBBB</color>
<color name="not_in_b_too">#AAAAAA</color>
<color name="not_in_a">#AAAAAA</color>
</resources>
La fusión debe contener todas las líneas a lo largo de estas reglas simples:
- cualquier línea que solo esté en uno de los archivos
- Si una línea tiene la misma etiqueta de nombre pero un valor diferente, tome el valor de la segunda
Quiero aplicar esta tarea dentro de un script bash, por lo que no necesariamente debe hacerse con diff y patch, si otro programa es mejor

diffpuede decirle qué líneas están en un archivo pero no en el otro, sino solo en la granularidad de líneas enteras.patchsolo es adecuado para realizar los mismos cambios en un archivo similar (tal vez una versión diferente del mismo archivo o un archivo completamente diferente donde, sin embargo, los números de línea y las líneas circundantes para cada cambio son idénticos a su archivo original). Entonces no, no son particularmente adecuados para esta tarea. Es posible que desee echar un vistazo,wdiffpero la solución probablemente requiera un script personalizado. Dado que sus datos se parecen a XML, es posible que desee buscar alguna herramienta XSL.Respuestas:
No necesitas
patchpara esto; es para extraer cambios y enviarlos sin la parte inalterada del archivo.La herramienta para fusionar dos versiones de un archivo es
merge, pero tal como se@vonbrandescribió, necesita el archivo "base" del cual sus dos versiones divergieron. Para hacer una fusión sin ella, usediffasí:Incluirá cada conjunto de cambios en los comandos de estilo C
#ifdef/#ifndef"preprocesador", como este:Si una línea o región difiere entre los dos archivos, obtendrá un "conflicto", que se ve así:
Así que guarde el resultado en un archivo y ábralo en un editor. Busque cualquier lugar donde
#elseaparezca y resuélvalos manualmente. Luego guarde el archivo y ejecútelogrep -vpara deshacerse del resto#if(n)defy las#endiflíneas:En el futuro, guarde la versión original del archivo.
mergepuede darle mejores resultados con la ayuda de la información adicional. (Pero tenga cuidado:mergeedita uno de los archivos en el lugar, a menos que lo use-p. Lea el manual).fuente
sed -e "s/^#else.*$/\/\/ conflict/g"#elselíneas manualmente, en el editor durante la resolución de conflictos.merge(1)probablemente esté más cerca de lo que desea, pero eso requiere un antepasado común para sus dos archivos.Una forma (¡sucia!) De hacerlo es:
grep(1)para excluirlassort -udeja una lista ordenada, elimina duplicadosHumm ... algo en la línea:
echo '<resources>'; grep -v resources file1 file2 | sort -u; echo '</resources>'podría hacer.
fuente
namein_b_but_different_valtiene un valor de#00AABBclasificación, lo colocará en la parte superior y borrará el segundo valor en lugar del primerodiff3funciona de la misma manera. Requerir un archivo ancestro común. ¿Por qué no hay una herramienta CLI simple que solo combine 2 archivos en función de lo que sediffmuestra?sdiff(1) - fusión lado a lado de diferencias de archivoUse la
--outputopción, esto fusionará interactivamente cualquiera de los dos archivos. Utiliza comandos simples para seleccionar un cambio o editar un cambio.Debe asegurarse de que la
EDITORvariable de entorno esté establecida. El editor predeterminado para comandos como "eb" suele seredun editor de línea .fuente
vimcomo EDITOR. Pero esta es la mejor solución, ¡también viene con eldiffcomando!Aquí una solución simple que funciona fusionando hasta 10 archivos :
tenga en cuenta que el argumento que viene primero tiene prioridad, por lo que debe llamar:
para mantener valores comunes guardados en
b.xmllugar dea.xml.script b.xml a.xmlsalidas:fuente
Otro truco horrible, podría simplificarse, pero: P
fuente
OK, segundo intento, ahora en Perl (¡ no calidad de producción, sin verificación!):
fuente
Otro, usando cut and grep ... (toma a.xml b.xml como argumentos)
fuente
echoes la acción predeterminada, por lo quexargs echoes superflua. ¿Por qué no simplemente detr '\n' '|'todos modos?