Diff de texte et correctifs : algorithme et outils en ligne

Diff : le calcul de différences omniprésent

De la gestion de versions Git à la revue de code, des changements de configuration à la synchronisation de données — Diff est une opération fondamentale du développement logiciel.

Scénario Type de Diff Outil
Changements de code Diff par ligne Git
Comparaison de configuration Diff par clé-valeur Outil de comparaison en ligne
Données JSON Diff structuré json-diff
Documents juridiques Diff sémantique Outil spécialisé
Vérification de traduction Diff par caractère Comparaison en ligne

I. Principes de l'algorithme Myers Diff

Idée centrale

L'algorithme Myers recherche le script d'édition le plus court (SES) qui convertit le texte source en texte cible — le moins d'opérations d'insertion/suppression.

Source : ABCABBA
Cible : CBABAC

Script d'édition :
- A    (supprimer A)
  B    (conserver B)
- C    (supprimer C)
  C    (conserver C → insérer C avant)
  A    (conserver A)
  B    (conserver B)
- B    (supprimer B)
  A    (conserver A)
+ C    (insérer C)

Diagramme de l'algorithme

      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

→ = droite (supprimer)  ↓ = bas (insérer)  ↘ = diagonale (conserver)

Complexité temporelle

Cas Complexité Description
Optimal O(ND) N=longueur du texte, D=nombre de différences
Pire O((N+M)D) Textes complètement différents
Typique O(N+D²) Peu de différences

II. Utilisation de l'outil de comparaison de texte de Tools Ku

Étapes de fonctionnement

  1. Ouvrez l'Outil de comparaison de texte
  2. Collez le texte original à gauche
  3. Collez le texte modifié à droite
  4. Consultez les résultats des différences :
    • Rouge : lignes supprimées
    • Vert : lignes ajoutées
    • Jaune : lignes modifiées
  5. Prend en charge la mise en évidence par caractère, précise jusqu'à chaque changement de caractère

Modes de comparaison

Mode Granularité Cas d'utilisation
Par ligne Comparaison par ligne Changements de code
Par mot Comparaison par mot Révisions de documents
Par caractère Comparaison par caractère Correction précise

III. Techniques spéciales de JSON Diff

Utilisation de l'outil JSON Diff

  1. Ouvrez l'Outil JSON Diff
  2. Collez deux données JSON
  3. Consultez les différences structurées :
    • Clés ajoutées/supprimées/modifiées
    • Changements de valeurs (y compris changements de type)
    • Chemins imbriqués

JSON Diff vs Diff textuel

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

// Modifié
{ "name": "张三", "age": 26, "tags": ["a", "c"], "email": "z@test.com" }
Méthode de comparaison Résultat
Diff textuel Affiche les différences par ligne, difficile à comprendre
JSON Diff age: 25→26, tags[1]: "b"→"c", +email: "z@test.com"

IV. Format Diff unifié

Spécification du format

--- 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"
 }
Symbole Signification
--- Fichier original
+++ Fichier modifié
@@ -a,b +c,d @@ Position de la différence (original à partir de la ligne a, b lignes ; modifié à partir de la ligne c, d lignes)
- Ligne supprimée
+ Ligne ajoutée
(espace) Ligne de contexte

V. Génération et application de correctifs

Générer un correctif

import * as Diff from 'diff';

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

// Générer le correctif
const patch = Diff.createPatch('file.txt', oldText, newText, 'old', 'new');
console.log(patch);

Sortie :

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

Appliquer un correctif

// Application en avant
const result = Diff.applyPatch(oldText, patch);

// Application en inverse (retour arrière)
const reversed = Diff.applyPatch(newText, Diff.reversePatch(patch));

Fusion à trois

const base = 'Texte original';
const branchA = 'Modification de A';
const branchB = 'Modification de B';

const merged = Diff.mergeDiff3(base, branchA, branchB);
// Fusion automatique, les conflits sont marqués avec <<<<<<< / ======= / >>>>>>>

VI. Scénarios d'application pratique

Détection de changements dans les fichiers de configuration

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('Ajouté :', JSON.stringify(part.value, null, 2));
  if (part.removed) console.log('Supprimé :', JSON.stringify(part.value, null, 2));
});

Vérification des fichiers de traduction

// Comparer la cohérence des clés de traduction chinois-anglais
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));

Tests de régression des réponses d'API

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('La réponse de l\'API ne correspond pas à l\'attendu');
}

VII. Optimisation des performances

Stratégie d'optimisation Effet Applicable à
Limiter les lignes de contexte Réduit la taille de sortie Fichiers volumineux
Prétraitement par hachage Ignore les lignes identiques Très gros fichiers
Comparaison par blocs Traitement parallèle Textes très longs
Niveau ligne avant niveau caractère Réduit la charge de calcul Fichiers de code
// Limiter les lignes de contexte
const patch = Diff.createPatch('file', old, new, '', '', { context: 3 });
#Diff#文本对比#Patch#Myers#代码审查