Text-Diff und Patches: Myers-Algorithmus und Online-Tools

Diff: Die allgegenwärtige Differenzberechnung

Von der Git-Versionsverwaltung bis zur Code-Überprüfung, von Konfigurationsänderungen bis zur Datensynchronisation — Diff ist eine Grundoperation in der Softwareentwicklung.

Szenario Diff-Typ Werkzeug
Codeänderungen Zeilen-Diff Git
Konfigurationsvergleich Schlüsselwert-Diff Online-Vergleichstool
JSON-Daten Strukturiertes Diff JSON-Diff
Rechtliche Dokumente Semantisches Diff Spezialisiertes Tool
Übersetzungsprüfung Zeichen-Diff Online-Vergleich

I. Prinzipien des Myers-Diff-Algorithmus

Kerngedanke

Der Myers-Algorithmus sucht das kürzeste Bearbeitungsskript (SES), das den Quelltext in den Zieltext umwandelt — die wenigsten Einfüge-/Löschoperationen.

Quelle: ABCABBA
Ziel: CBABAC

Bearbeitungsskript:
- A    (A löschen)
  B    (B beibehalten)
- C    (C löschen)
  C    (C beibehalten → C vorher einfügen)
  A    (A beibehalten)
  B    (B beibehalten)
- B    (B löschen)
  A    (A beibehalten)
+ C    (C einfügen)

Algorithmus-Diagramm

      0   1   2   3   4   5   6   7
  ┌───┬───┬───┬───┬───┬───┬───┬───┐
0 │ → │ ↘ │   │   │   │   │   │   │  A
  ├───┼───┼───┼───┼───┼───┼───┼───┤
1 │ ↓ │   │ ↘ │   │ → │ ↘ │   │   │  B
  ├───┼───┼───┼───┼───┼───┼───┼───┤
2 │   │ ↓ │   │ ↘ │ ↓ │   │ ↘ │   │  C
  ├───┼───┼───┼───┼───┼───┼───┼───┤
3 │   │   │ ↓ │   │   │ ↓ │   │ ↘ │  A
  ├───┼───┼───┼───┼───┼───┼───┼───┤
4 │   │   │   │ ↓ │ ↘ │   │ ↓ │   │  B
  ├───┼───┼───┼───┼───┼───┼───┼───┤
5 │   │   │   │   │ ↓ │   │   │ ↓ │  B
  ├───┼───┼───┼───┼───┼───┼───┼───┤
6 │   │   │   │   │   │ ↓ │ ↘ │   │  A
  └───┴───┴───┴───┴───┴───┴───┴───┘
    C   B   A   B   A   C   B   A

→ = rechts (löschen)  ↓ = unten (einfügen)  ↘ = diagonal (beibehalten)

Zeitkomplexität

Fall Komplexität Beschreibung
Optimal O(ND) N=Textlänge, D=Anzahl der Unterschiede
Schlechtester O((N+M)D) Völlig verschiedene Texte
Typisch O(N+D²) Wenige Unterschiede

II. Verwendung des Textvergleichstools von Tools Ku

Bedienungsschritte

  1. Öffnen Sie das Textvergleichstool
  2. Fügen Sie den Originaltext links ein
  3. Fügen Sie den geänderten Text rechts ein
  4. Sehen Sie sich die Diff-Ergebnisse an:
    • Rot: gelöschte Zeilen
    • Grün: hinzugefügte Zeilen
    • Gelb: geänderte Zeilen
  5. Unterstützt zeichenweise Diff-Hervorhebung, präzise bis zu jeder Zeichenänderung

Vergleichsmodi

Modus Granularität Anwendungsfall
Zeilenweise Vergleich pro Zeile Codeänderungen
Wortweise Vergleich pro Wort Dokumentrevisionen
Zeichenweise Vergleich pro Zeichen Präzise Korrektur

III. Spezielle JSON-Diff-Techniken

Verwendung des JSON-Diff-Tools

  1. Öffnen Sie das JSON-Diff-Tool
  2. Fügen Sie zwei JSON-Daten ein
  3. Sehen Sie sich die strukturierten Unterschiede an:
    • Hinzugefügte/gelöschte/geänderte Schlüssel
    • Wertänderungen (einschließlich Typänderungen)
    • Verschachtelte Pfade

JSON-Diff vs. Text-Diff

// Original
{ "name": "张三", "age": 25, "tags": ["a", "b"] }

// Geändert
{ "name": "张三", "age": 26, "tags": ["a", "c"], "email": "z@test.com" }
Vergleichsmethode Ergebnis
Text-Diff Zeigt Unterschiede zeilenweise, schwer verständlich
JSON-Diff age: 25→26, tags[1]: "b"→"c", +email: "z@test.com"

IV. Unified-Diff-Format

Formatspezifikation

--- a/config.json
+++ b/config.json
@@ -1,5 +1,6 @@
 {
   "name": "my-project",
-  "version": "1.0.0",
+  "version": "2.0.0",
   "description": "A tool",
-  "private": true
+  "private": true,
+  "license": "MIT"
 }
Symbol Bedeutung
--- Originaldatei
+++ Geänderte Datei
@@ -a,b +c,d @@ Diff-Position (Original ab Zeile a, b Zeilen; Geändert ab Zeile c, d Zeilen)
- Gelöschte Zeile
+ Hinzugefügte Zeile
(Leerzeichen) Kontextzeile

V. Patch-Generierung und -Anwendung

Patch generieren

import * as Diff from 'diff';

const oldText = 'Hello World\nGoodbye World';
const newText = 'Hello World\nGoodbye Cruel World';

// Patch generieren
const patch = Diff.createPatch('file.txt', oldText, newText, 'old', 'new');
console.log(patch);

Ausgabe:

--- old/file.txt
+++ new/file.txt
@@ -1,2 +1,2 @@
 Hello World
-Goodbye World
+Goodbye Cruel World

Patch anwenden

// Vorwärts anwenden
const result = Diff.applyPatch(oldText, patch);

// Rückwärts anwenden (Rückgängigmachung)
const reversed = Diff.applyPatch(newText, Diff.reversePatch(patch));

Drei-Wege-Zusammenführung

const base = 'Originaltext';
const branchA = 'Änderung von A';
const branchB = 'Änderung von B';

const merged = Diff.mergeDiff3(base, branchA, branchB);
// Automatische Zusammenführung, Konflikte werden mit <<<<<<< / ======= / >>>>>>> markiert

VI. Praktische Anwendungsszenarien

Erkennung von Konfigurationsdateiänderungen

const oldConfig = JSON.parse(fs.readFileSync('config.old.json', 'utf-8'));
const newConfig = JSON.parse(fs.readFileSync('config.new.json', 'utf-8'));

const diff = Diff.diffJson(oldConfig, newConfig);
diff.forEach(part => {
  if (part.added) console.log('Hinzugefügt:', JSON.stringify(part.value, null, 2));
  if (part.removed) console.log('Gelöscht:', JSON.stringify(part.value, null, 2));
});

Übersetzungsdatei-Überprüfung

// Konsistenz der chinesisch-englischen Übersetzungsschlüssel vergleichen
const zhKeys = Object.keys(flatten(zhTranslation));
const enKeys = Object.keys(flatten(enTranslation));

const missingInEn = zhKeys.filter(k => !enKeys.includes(k));
const missingInZh = enKeys.filter(k => !zhKeys.includes(k));

API-Antwort-Regressionstests

const expected = await fs.readFile('fixtures/expected.json', 'utf-8');
const actual = await fetch('/api/data').then(r => r.json());

const diff = Diff.diffJson(JSON.parse(expected), actual);
if (diff.some(d => d.added || d.removed)) {
  throw new Error('API-Antwort entspricht nicht der Erwartung');
}

VII. Leistungsoptimierung

Optimierungsstrategie Wirkung Anwendbar auf
Kontextzeilen begrenzen Reduziert Ausgabegröße Große Dateien
Hash-Vorverarbeitung Überspringt identische Zeilen Sehr große Dateien
Blockweiser Vergleich Parallele Verarbeitung Sehr lange Texte
Zeilenebene vor Zeichenebene Reduziert Rechenaufwand Codedateien
// Kontextzeilen begrenzen
const patch = Diff.createPatch('file', old, new, '', '', { context: 3 });
#Diff#文本对比#Patch#Myers#代码审查