Eu li sobre diff e patch, mas não consigo descobrir como aplicar o que preciso. Eu acho que é bem simples, então, para mostrar meu problema, pegue estes dois arquivos:
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>
Eu quero ter uma saída, que se parece com isso (ordem não 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>
A mesclagem deve conter todas as linhas ao longo destas regras simples:
- qualquer linha que esteja apenas em um dos arquivos
- se uma linha tiver o mesmo nome, mas um valor diferente, use o valor do segundo
Eu quero aplicar esta tarefa dentro de um script bash, para que não seja necessário fazer nessesariamente o diff e o patch, se outro programa for mais adequado
diff
pode dizer quais linhas estão em um arquivo, mas não no outro, mas apenas na granularidade de linhas inteiras.patch
é adequado apenas para fazer as mesmas alterações em um arquivo semelhante (talvez uma versão diferente do mesmo arquivo ou um arquivo totalmente diferente, no entanto, os números das linhas e as linhas adjacentes de cada alteração são idênticas ao seu arquivo original). Portanto, não, eles não são particularmente adequados para esta tarefa. Você pode querer dar uma olhada,wdiff
mas a solução provavelmente requer um script personalizado. Como seus dados se parecem com XML, convém procurar alguma ferramenta XSL.Respostas:
Você não precisa
patch
disso; é para extrair alterações e enviá-las sem a parte inalterada do arquivo.A ferramenta para mesclar duas versões de um arquivo é
merge
, mas conforme foi@vonbrand
escrito, você precisa do arquivo "base" do qual suas duas versões divergiram. Para fazer uma mesclagem sem ela, use odiff
seguinte:Ele incluirá cada conjunto de alterações nos comandos de estilo C
#ifdef
/#ifndef
"pré-processador", assim:Se uma linha ou região diferir entre os dois arquivos, você receberá um "conflito", que se parece com isso:
Portanto, salve a saída em um arquivo e abra-a em um editor. Pesquise os locais que
#else
aparecerem e resolva-os manualmente. Em seguida, salve o arquivo e execute-ogrep -v
para se livrar do restante#if(n)def
e das#endif
linhas:No futuro, salve a versão original do arquivo.
merge
pode fornecer resultados muito melhores com a ajuda de informações extras. (Mas tenha cuidado:merge
edita um dos arquivos no local, a menos que você o utilize-p
. Leia o manual).fonte
sed -e "s/^#else.*$/\/\/ conflict/g"
#else
linhas manualmente, no editor durante a resolução de conflitos.merge(1)
provavelmente está mais próximo do que você deseja, mas isso requer um ancestral comum para seus dois arquivos.Uma maneira (suja!) De fazer isso é:
grep(1)
para excluí-lassort -u
sai de uma lista classificada, elimina duplicatasHumm ... algo do tipo:
echo '<resources>'; grep -v resources file1 file2 | sort -u; echo '</resources>'
pode fazer.
fonte
name
in_b_but_different_val
tem um valor de#00AABB
tipo vai colocar isso em cima e apaga o segundo valor, em vez do primeirodiff3
funciona da mesma maneira. Exigindo um arquivo ancestral comum. Por que não existe uma ferramenta CLI simples que apenas mescla 2 arquivos com base no que édiff
mostrado?sdiff
(1) - mesclagem lado a lado das diferenças de arquivoUse a
--output
opção, isso mesclará interativamente quaisquer dois arquivos. Você usa comandos simples para selecionar uma alteração ou editar uma alteração.Você deve se certificar de que a
EDITOR
variável de ambiente esteja definida. O editor padrão para comandos como "eb" é geralmenteed
um editor de linha .fonte
vim
como o EDITOR é melhor. Mas esta é a melhor solução, também vem com odiff
comando!Aqui está uma solução simples que funciona mesclando até 10 arquivos :
observe que o argumento que vem primeiro tem precedência, então você deve ligar para:
para obter valores comuns mantidos em
b.xml
vez dea.xml
.script b.xml a.xml
saídas:fonte
Outro truque horrível - poderia ser simplificado, mas: P
fonte
OK, segunda tentativa, agora em Perl ( sem qualidade de produção, sem verificação!):
fonte
Outro, usando cut e grep ... (usa a.xml b.xml como argumentos)
fonte
echo
é a ação padrão, portantoxargs echo
é supérflua. Por que você simplesmente não étr '\n' '|'
assim?