Jak porównać dwa pliki YAML bez kłopotów z wcięciami
Najszybszy sposób na porównanie dwóch plików YAML to wklejenie obu do narzędzia diff wyświetlającego je obok siebie, znormalizowanie wcięć i odczytanie wyróżnionych wierszy. Porównywanie to łatwa część. W YAML szum jest bardziej podstępny niż zwykle: zabłąkany tabulator, przestawiony klucz albo wartość, którą ktoś ujął w cudzysłów, mogą sprawić, że dwa pliki ładujące się do tych samych danych wyglądają, jakby nie miały nic wspólnego.
Ten przewodnik pokazuje, jak uzyskać czysty, wiarygodny diff YAML. Przyjrzymy się, dlaczego dwa równoważne pliki rozjeżdżają się na papierze, które metody warto znać i opracowanemu przykładowi, za którym możesz podążać. Jeśli chcesz tylko narzędzia, nasza strona porównywania YAML robi to wszystko w przeglądarce.
Dlaczego pliki YAML są zwodniczo trudne do porównania
YAML to format wrażliwy na białe znaki (zobacz specyfikację YAML 1.2.2), i właśnie to czyni diffy podchwytliwymi. Wcięcie niesie znaczenie, ale ilość wcięcia nie, dopóki jest spójna. Tak więc plik z wcięciem dwoma spacjami i inny z czterema mogą załadować się do identycznej struktury, podczas gdy każdy wiersz wygląda inaczej dla diffu tekstowego.
Oto kluczowy fakt, który trzeba zapamiętać: mapping YAML to zbiór par klucz/wartość i, podobnie jak obiekty JSON, kolejność tych kluczy nie zmienia danych. Więc to:
name: Ada Lovelace
role: editor
i to:
role: editor
name: Ada Lovelace
ładują się do tego samego mappingu, nawet jeśli diff wierszowy maluje je na czerwono i zielono. Elementy sekwencji są natomiast uporządkowane, więc przestawienie listy jest prawdziwą zmianą.
| Co widzisz w diffie | Czy to prawdziwa zmiana? | Co zrobić |
|---|---|---|
| Wcięcie 2 vs 4 spacje | Nie, liczy się tylko spójność | Sformatuj oba na tę samą szerokość |
| Klucze mappingu w innej kolejności | Nie, mappingi są nieuporządkowane | Posortuj klucze po obu stronach |
true vs "true" | Tak, boolean vs ciąg | Zbadaj to, jest prawdziwe |
name: Ada vs name: "Ada" | Nie, ta sama wartość ciągu | Znormalizuj cudzysłowy |
Styl flow [a, b] vs lista blokowa | Nie, ta sama sekwencja | Wybierz jeden styl dla obu |
| Elementy sekwencji w innej kolejności | Tak, sekwencje są uporządkowane | Zbadaj to, jest prawdziwe |
Dwa wiersze tam to prawdziwe pułapki. true bez cudzysłowów to boolean;
w cudzysłowach to ciąg "true", a to rozróżnienie spowodowało prawdziwe awarie. Ale
name: Ada i name: "Ada" to ten sam ciąg. Jeśli chcesz
szczegółów technicznych o tym, jak parser to rozstrzyga, sekcja specyfikacji o
core schema
jest punktem odniesienia.
Cztery sposoby porównywania YAML i kiedy po który sięgnąć
Nie ma jednej najlepszej metody. Zależy to od tego, gdzie są pliki i czego chcesz się dowiedzieć. Oto jak wypadają popularne opcje.
| Metoda | Najlepsza do | Wysiłek | Rozumie YAML? |
|---|---|---|---|
| Sprawdzanie wzrokiem | Maleńkie pliki, jeden lub dwa klucze | Niski | Nie, to ty jesteś parserem |
| Narzędzie diff online | Szybkie sprawdzenia, wklejanie skądkolwiek | Niski | Z formatowaniem, tak |
Wiersz poleceń (yq) | Pliki na dysku, skrypty, sortowanie kluczy | Średni | Tak, gdy najpierw posortujesz |
IDE lub git diff | Pliki już w repozytorium | Niski, jeśli zacommitowane | Domyślnie wierszowo |
Dla większości ludzi narzędzie w przeglądarce wygrywa szybkością: nic do instalowania, a fragment możesz wkleić wprost z manifestu Kubernetes lub konfiguracji CI. Haczykiem jest szum formatowania, którym zajmiemy się dalej. Jeśli żyjesz w terminalu, yq to narzędzie do nauki, a klucze potrafi sortować tak samo, jak jq robi to dla JSON.
Najszybsze czyste porównanie, krok po kroku
To rutyna, której używam, gdy ktoś podaje mi dwa manifesty i pyta „co się różni?". Zajmuje około piętnastu sekund.
- Otwórz narzędzie porównywania YAML.
- Wklej oryginał po lewej, a nową wersję po prawej.
- Kliknij Formatuj po obu stronach, aby miały to samo wcięcie.
- Włącz sortowanie kluczy, aby przestawione klucze mappingu przestały pojawiać się jako zmiany.
- Odczytaj wynik. Zielony to dodane, czerwony to usunięte, a zmieniona wartość pojawia się jako jeden z każdego koloru.
Kroki trzeci i czwarty to cała sztuczka. Gdy oba pliki używają tego samego wcięcia, a ich klucze są posortowane, jedyne, co zostaje do wyróżnienia, to to, co naprawdę się zmieniło. Nasz silnik diff opiera się na diff-match-patch od Google, który najpierw porównuje wiersz po wierszu, dzięki czemu pozostaje szybki nawet przy długich plikach.
Opracowany przykład
Powiedzmy, że przeglądasz zmianę w rekordzie użytkownika. Oto stan przed:
name: Ada Lovelace
role: editor
active: true
seats: 3
A oto stan po, tak jak przekazał ci go kolega z zespołu:
active: true
name: Ada Lovelace
role: admin
seats: 5
team: platform
Wrzuć je do surowego diffu wierszowego, a wygląda, jakby prawie każdy wiersz się przesunął, bo klucze są w innej kolejności. Sformatuj i posortuj oba, a prawdziwa historia jest krótka:
| Klucz | Przed | Po | Zmiana |
|---|---|---|---|
role | editor | admin | Zmodyfikowano |
seats | 3 | 5 | Zmodyfikowano |
team | — | platform | Dodano |
name | Ada Lovelace | Ada Lovelace | Bez zmian |
active | true | true | Bez zmian (tylko przeniesiono) |
Trzy prawdziwe edycje: awans roli, liczba miejsc i nowy klucz zespołu. Przestawienie
było szumem. Ten awans z editor na admin to dokładnie ten
rodzaj rzeczy, który chcesz wychwycić w przeglądzie, a łatwo go przeoczyć, gdy jest
pogrzebany pod fałszywymi alarmami.
Eliminowanie szumu formatowania w wierszu poleceń
Jeśli twoje pliki są już na dysku, ten sam pomysł „sformatuj i posortuj" działa z
dwoma krótkimi poleceniami. yq potrafi posortować klucze i ponownie
wyemitować formę kanoniczną, więc zwykły diff po tym jest uczciwy:
yq -P 'sort_keys(..)' old.yaml > old.sorted.yaml
yq -P 'sort_keys(..)' new.yaml > new.sorted.yaml
diff old.sorted.yaml new.sorted.yaml
Teraz diff zgłasza tylko wartości, które naprawdę się zmieniły, bo oba
pliki mają to samo wcięcie i tę samą kolejność kluczy. To terminalowy odpowiednik
kliknięcia Formatuj i sortowania kluczy w przeglądarce.
Pułapki unikalne dla YAML
Kilka funkcji YAML powoduje diffy, które zaskakują ludzi. Anchors i aliases
(&name i *name) pozwalają jednemu plikowi powtórzyć
wartość przez referencję, podczas gdy inny wypisuje ją w całości; oba ładują się do
tych samych danych, ale czytają się zupełnie inaczej. Niesławny „problem Norwegii"
to kolejna: niecytowane no, off i yes mogą
być parsowane jako booleany w starszych parserach YAML 1.1, więc
country: NO może stać się false. YAML 1.2 naprawił schemat,
ale wiele narzędzi nadal dostarcza zachowanie 1.1. Gdy wartość wygląda, jakby
zmieniła typ, to pierwsza rzecz do sprawdzenia.
Częste pułapki, na które trzeba uważać
| Pułapka | Dlaczego gryzie | Rozwiązanie |
|---|---|---|
| Tabulatory do wcięć | YAML zabrania tabulatorów do wcięć; plik może się nawet nie sparsować | Najpierw zamień tabulatory na spacje |
| Skalary z cudzysłowami i bez | "true" to ciąg, true to boolean | To może być prawdziwa zmiana, nie lekceważ jej |
| Anchors i aliases | Jeden plik wstawia wartość w miejscu, drugi się do niej odwołuje | Rozwiąż anchors, a potem porównaj rozwiniętą formę |
| Problem Norwegii | no może być parsowane jako false w YAML 1.1 | Ujmij dwuznaczne ciągi w cudzysłów; sprawdź wersję parsera |
| Białe znaki na końcu wiersza | Niewidoczne spacje po wartości pojawiają się jako zmiana | Przytnij końcowe białe znaki przed porównaniem |
YAML i JSON są sobie bliższe, niż się wydaje
Każdy dokument JSON jest prawidłowym YAML, ponieważ YAML 1.2 to nadzbiór JSON. To przydatne do porównywania: jeśli wcięcia lub anchors dają ci się we znaki, przekonwertuj oba pliki na JSON, sformatuj je tak samo i porównaj to. Wiele parserów, w tym PyYAML, przeprowadza YAML w obie strony do prostej struktury danych, którą możesz ponownie wyemitować jako JSON, co zdziera różnice stylistyczne i zostawia same dane.
Powiązane narzędzia
YAML rzadko podróżuje sam. Jeśli porównujesz formę JSON tych samych danych,
porównanie JSON stosuje ten sam pomysł. Ustawienia
środowiska i pliki .env dobrze układają się na stronie
porównania konfiguracji, a przeglądanie zmian
między dwoma wywołaniami API to to, do czego zbudowano
diff odpowiedzi API.
Najczęściej zadawane pytania
- Czy porównywanie plików YAML online przesyła je gdziekolwiek?
- Na comparetext.org diff działa w twojej przeglądarce. Dwa pliki YAML są porównywane przez JavaScript na twoim własnym komputerze, więc nic nie jest wysyłane na serwer, dopóki wyraźnie nie klikniesz Zapisz lub Udostępnij. To czyni go bezpiecznym dla manifestów Kubernetes, konfiguracji CI i innych danych, których nie chciałbyś wklejać na stronę przesyłającą wszystko przy każdym naciśnięciu klawisza.
- Dlaczego moje dwa pliki YAML pokazują każdy wiersz jako różny?
- Niemal zawsze to formatowanie, a nie prawdziwe zmiany. Jeden plik ma wcięcie dwoma spacjami, drugi czterema, albo klucze mappingu są w innej kolejności, albo jeden używa cudzysłowów, a drugi nie. Sformatuj obie strony do tego samego wcięcia i posortuj klucze, aby kolejność przestała mieć znaczenie. Po tym diff zwykle kurczy się do garstki wartości, które naprawdę się zmieniły.
- Czy szerokość wcięcia ma znaczenie przy porównywaniu YAML?
- Nie dla znaczenia, tylko dla spójności. YAML używa wcięcia, by pokazać strukturę, ale nie obchodzi go, czy używasz dwóch czy czterech spacji, dopóki każdy poziom jest spójny w obrębie pliku. Tak więc plik z dwiema spacjami i plik z czterema mogą zawierać identyczne dane, a mimo to wyglądać zupełnie inaczej dla diffu tekstowego. Sformatowanie obu do tej samej szerokości usuwa tę fałszywą różnicę. Tabulatory natomiast nie są w ogóle dozwolone do wcięć.
- Jak porównać YAML, ignorując kolejność kluczy?
- Klucze mappingu YAML są nieuporządkowane, więc dwa pliki z tymi samymi kluczami w innej kolejności zawierają te same dane. Aby diff tekstowy się z tym zgodził, posortuj klucze po obu stronach przed porównaniem. W przeglądarce użyj opcji sortowania kluczy (kanonizacja). W wierszu poleceń yq robi to z sort_keys. Gdy oba pliki mają klucze w tej samej posortowanej kolejności, pojawiają się tylko prawdziwe zmiany wartości. Elementy sekwencji zachowują kolejność, więc ich nie sortuj.
- Czym jest problem Norwegii w YAML?
- To klasyczna pułapka YAML, w której niecytowana wartość NO jest parsowana jako boolean false zamiast ciągu "NO", więc kod kraju dla Norwegii staje się false. Dzieje się to w parserach YAML 1.1, które traktują yes, no, on i off jako booleany. YAML 1.2 zawęził reguły, ale wiele narzędzi nadal dostarcza zachowanie 1.1. Jeśli wartość wygląda, jakby zmieniła się ze słowa na true lub false w twoim diffie, niecytowany ciąg podobny do boolean jest prawdopodobną przyczyną. Ujęcie wartości w cudzysłów to naprawia.
- Czy mogę porównywać duże pliki YAML bez zawieszania strony?
- Tak, do pewnego stopnia. Diff w trybie wierszowym pozostaje szybki przy plikach z tysiącami wierszy, bo najpierw porównuje całe wiersze, a nie każdy znak. Bardzo duże pliki (kilka megabajtów) lepiej obsłużyć narzędziem wiersza poleceń, jak yq lub git diff, które strumieniuje dane. Dla wszystkiego, co da się wygodnie przewinąć w przeglądarce, diff online jest szybszą opcją.
Gotów spróbować? Wklej swoje pliki do narzędzia porównywania YAML i zobacz, co się zmieniło.