Diff de Texto: Algoritmo e Uso de Ferramentas Online

TextoText processing tools

Diff: o cálculo de diferenças onipresente

Do gerenciamento de versões do Git à revisão de código, de mudanças de configuração à sincronização de dados — Diff é uma operação fundamental no desenvolvimento de software.

Cenário Tipo de Diff Ferramenta
Mudanças de código Diff por linha Git
Comparação de configuração Diff por chave-valor Ferramenta de comparação online
Dados JSON Diff estruturado json-diff
Documentos legais Diff semântico Ferramenta especializada
Revisão de tradução Diff por caractere Comparação online

I. Princípios do Algoritmo Myers Diff

Ideia central

O algoritmo Myers busca o script de edição mais curto (SES) que converte o texto fonte no texto destino — o menor número de operações de inserção/remoção.

Fonte: ABCABBA
Destino: CBABAC

Script de edição:
- A    (remover A)
  B    (manter B)
- C    (remover C)
  C    (manter C → inserir C antes)
  A    (manter A)
  B    (manter B)
- B    (remover B)
  A    (manter A)
+ C    (inserir C)

Diagrama do algoritmo

      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

→ = direita (remover)  ↓ = baixo (inserir)  ↘ = diagonal (manter)

Complexidade de tempo

Caso Complexidade Descrição
Ótimo O(ND) N=comprimento do texto, D=número de diferenças
Pior O((N+M)D) Textos completamente diferentes
Típico O(N+D²) Poucas diferenças

II. Uso da ferramenta de comparação de texto do Tools Ku

Passos de operação

  1. Abra a Ferramenta de comparação de texto
  2. Cole o texto original no lado esquerdo
  3. Cole o texto modificado no lado direito
  4. Veja os resultados das diferenças:
    • Vermelho: linhas removidas
    • Verde: linhas adicionadas
    • Amarelo: linhas modificadas
  5. Suporta destaque de diferenças por caractere, preciso até cada mudança de caractere

Modos de comparação

Modo Granularidade Caso de uso
Por linha Comparação por linha Mudanças de código
Por palavra Comparação por palavra Revisão de documentos
Por caractere Comparação por caractere Correção precisa

III. Técnicas Especiais de JSON Diff

Usando a ferramenta JSON Diff

  1. Abra a Ferramenta JSON Diff
  2. Cole dois dados JSON
  3. Veja as diferenças estruturadas:
    • Chaves adicionadas/removidas/modificadas
    • Mudanças de valores (incluindo mudanças de tipo)
    • Caminhos aninhados

JSON Diff vs Diff de texto

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

// Modificado
{ "name": "张三", "age": 26, "tags": ["a", "c"], "email": "z@test.com" }
Método de comparação Resultado
Diff de texto Mostra diferenças por linha, difícil de entender
JSON Diff age: 25→26, tags[1]: "b"→"c", +email: "z@test.com"

IV. Formato Diff Unificado

Especificação do formato

--- 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"
 }
Símbolo Significado
--- Arquivo original
+++ Arquivo modificado
@@ -a,b +c,d @@ Posição da diferença (original da linha a, b linhas; modificado da linha c, d linhas)
- Linha removida
+ Linha adicionada
(espaço) Linha de contexto

V. Geração e Aplicação de Patches

Gerar patch

import * as Diff from 'diff';

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

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

Saída:

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

Aplicar patch

// Aplicar para frente
const result = Diff.applyPatch(oldText, patch);

// Aplicar reversamente (reverter)
const reversed = Diff.applyPatch(newText, Diff.reversePatch(patch));

Mesclagem de três vias

const base = 'Texto original';
const branchA = 'Modificação de A';
const branchB = 'Modificação de B';

const merged = Diff.mergeDiff3(base, branchA, branchB);
// Mesclagem automática, marca conflitos com <<<<<<< / ======= / >>>>>>>

VI. Cenários de Aplicação Prática

Detecção de mudanças em arquivos de configuração

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

Revisão de arquivos de tradução

// Comparar a consistência de chaves de tradução chinês-inglês
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));

Testes de regressão de respostas de 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('A resposta da API não corresponde ao esperado');
}

VII. Otimização de Desempenho

Estratégia de otimização Efeito Aplicável a
Limitar linhas de contexto Reduz o tamanho da saída Arquivos grandes
Pré-processamento com hash Pula linhas idênticas Arquivos muito grandes
Comparação por blocos Processamento paralelo Textos muito longos
Nível de linha antes do nível de caractere Reduz a carga de cálculo Arquivos de código
// Limitar linhas de contexto
const patch = Diff.createPatch('file', old, new, '', '', { context: 3 });
#Diff#文本对比#Patch#Myers#代码审查