Czytałem o diff i łatce, ale nie mogę wymyślić, jak zastosować to, czego potrzebuję. Myślę, że to dość proste, więc aby pokazać mój problem, weź te dwa pliki:
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>
Chcę mieć wynik, który wygląda następująco (kolejność nie ma znaczenia):
<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>
Scalanie powinno zawierać wszystkie wiersze według tych prostych zasad:
- dowolny wiersz, który znajduje się tylko w jednym z plików
- jeśli wiersz ma tę samą plakietkę, ale inną wartość, należy pobrać wartość z drugiego
Chcę zastosować to zadanie w skrypcie bash, więc nie trzeba go koniecznie wykonywać przy użyciu diff i łatki, jeśli inny program lepiej pasuje
diff
może powiedzieć, które linie są w jednym pliku, ale nie w drugim, ale tylko na ziarnistości całych linii.patch
nadaje się tylko do dokonywania tych samych zmian w podobnym pliku (być może innej wersji tego samego pliku lub zupełnie innym pliku, w którym jednak numery linii i otaczające linie dla każdej zmiany są identyczne z plikiem oryginalnym). Więc nie, nie są szczególnie odpowiednie do tego zadania. Możesz rzucić okiem,wdiff
ale rozwiązanie prawdopodobnie wymaga niestandardowego skryptu. Ponieważ twoje dane wyglądają jak XML, możesz poszukać jakiegoś narzędzia XSL.Odpowiedzi:
Nie potrzebujesz
patch
tego; służy do wyodrębniania zmian i wysyłania ich bez niezmienionej części pliku.Narzędziem do scalania dwóch wersji pliku jest
merge
, ale jak@vonbrand
napisano, potrzebujesz pliku „podstawowego”, z którego rozdzieliły się twoje dwie wersje. Aby wykonać scalanie bez niego, użyjdiff
następującego:Będzie zawierać każdy zestaw zmian w poleceniach w stylu C
#ifdef
/#ifndef
„preprocesorze”, takich jak:Jeśli linia lub region różnią się między dwoma plikami, pojawi się „konflikt”, który wygląda następująco:
Zapisz wynik w pliku i otwórz go w edytorze. Wyszukaj wszystkie znalezione miejsca
#else
i rozwiąż je ręcznie. Następnie zapisz plik i uruchom go,grep -v
aby pozbyć się pozostałych#if(n)def
i#endif
wierszy:W przyszłości zapisz oryginalną wersję pliku.
merge
może dać ci znacznie lepsze wyniki za pomocą dodatkowych informacji. (Ale bądź ostrożny:merge
edytuje jeden z plików w miejscu, chyba że używasz-p
. Przeczytaj instrukcję).źródło
sed -e "s/^#else.*$/\/\/ conflict/g"
#else
linie ręcznie w edytorze podczas rozwiązywania konfliktu.merge(1)
jest prawdopodobnie bliżej tego, czego chcesz, ale wymaga to wspólnego przodka dla twoich dwóch plików.(Brudnym!) Sposobem na zrobienie tego jest:
grep(1)
aby je wykluczyćsort -u
pozostawia posortowaną listę, eliminuje duplikatyHumm ... coś w stylu:
echo '<resources>'; grep -v resources file1 file2 | sort -u; echo '</resources>'
może zrobić.
źródło
name
in_b_but_different_val
ma#00AABB
sort, umieści tę wartość na górze i usunie drugą wartość zamiast pierwszejdiff3
działa w ten sam sposób. Wymagający wspólnego pliku przodka. Dlaczego nie ma prostego narzędzia CLI, które po prostu łączy 2 pliki w zależności od tegodiff
, co pokazuje.sdiff
(1) - łączenie różnic w plikach obok siebieUżyj
--output
opcji, spowoduje to interaktywne scalenie dowolnych dwóch plików. Korzystasz z prostych poleceń, aby wybrać zmianę lub edytować zmianę.Należy upewnić się, że
EDITOR
zmienna środowiskowa jest ustawiona. Domyślnym edytorem poleceń takich jak „eb” jest zazwyczajed
edytor liniowy .źródło
vim
jako EDYTORA jest lepsze. Ale to najlepsze rozwiązanie, ma teżdiff
polecenie!Oto proste rozwiązanie, które działa scalając do 10 plików :
pamiętaj, że arg, który jest pierwszy, ma pierwszeństwo, więc musisz zadzwonić:
aby uzyskać wspólne wartości,
b.xml
a niea.xml
.script b.xml a.xml
outs:źródło
Kolejny okropny hack - można uprościć, ale: P
źródło
OK, druga próba, teraz w Perlu ( nie jakość produkcji, brak sprawdzania!):
źródło
Kolejny, wykorzystujący cut i grep ... (przyjmuje argumenty a.xml b.xml)
źródło
echo
jest działaniem domyślnym, więcxargs echo
jest zbyteczne. Dlaczego tak po prostu nie jesteśtr '\n' '|'
?