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
diff
puede decirle qué líneas están en un archivo pero no en el otro, sino solo en la granularidad de líneas enteras.patch
solo 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,wdiff
pero 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
patch
para 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@vonbrand
escribió, necesita el archivo "base" del cual sus dos versiones divergieron. Para hacer una fusión sin ella, usediff
así: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
#else
aparezca y resuélvalos manualmente. Luego guarde el archivo y ejecútelogrep -v
para deshacerse del resto#if(n)def
y las#endif
líneas:En el futuro, guarde la versión original del archivo.
merge
puede darle mejores resultados con la ayuda de la información adicional. (Pero tenga cuidado:merge
edita uno de los archivos en el lugar, a menos que lo use-p
. Lea el manual).fuente
sed -e "s/^#else.*$/\/\/ conflict/g"
#else
lí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 -u
deja 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
name
in_b_but_different_val
tiene un valor de#00AABB
clasificación, lo colocará en la parte superior y borrará el segundo valor en lugar del primerodiff3
funciona 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 sediff
muestra?sdiff
(1) - fusión lado a lado de diferencias de archivoUse la
--output
opció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
EDITOR
variable de entorno esté establecida. El editor predeterminado para comandos como "eb" suele sered
un editor de línea .fuente
vim
como EDITOR. Pero esta es la mejor solución, ¡también viene con eldiff
comando!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.xml
lugar dea.xml
.script b.xml a.xml
salidas: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
echo
es la acción predeterminada, por lo quexargs echo
es superflua. ¿Por qué no simplemente detr '\n' '|'
todos modos?