Comparador de Textos
Compare dois textos lado a lado e destaque as diferenças linha por linha
Texto A
Texto B
O que é diff de texto?
Um diff de texto (abreviação de "difference", diferença) é o resultado da comparação de dois blocos de texto para identificar quais linhas foram adicionadas, removidas ou mantidas inalteradas. O conceito tem origem no utilitário diff do Unix, lançado pela primeira vez em 1974 como parte do Unix Versão 5. Hoje, o diff de texto é a base dos sistemas de controle de versão como o Git, onde cada commit armazena um diff em vez de uma cópia completa de cada arquivo.
Um algoritmo de diff encontra a Subsequência Comum Mais Longa (LCS, do inglês Longest Common Subsequence) entre duas sequências de linhas. As linhas presentes na LCS são marcadas como inalteradas. As linhas no texto original que não fazem parte da LCS são marcadas como removidas. As linhas no texto modificado que não fazem parte da LCS são marcadas como adicionadas. O resultado é o conjunto mínimo de alterações necessárias para transformar um texto no outro.
A saída do diff existe em vários formatos. O unified diff (padrão para git diff) prefixia linhas removidas com um sinal de menos e linhas adicionadas com um sinal de mais. O diff lado a lado organiza ambos os textos em colunas paralelas. Esta ferramenta usa comparação linha por linha com saída codificada por cores: verde para adições, vermelho para remoções e neutro para linhas inalteradas. As linhas inalteradas são exibidas sem prefixo por padrão, mas podem ser ocultadas para focar apenas no que mudou.
Por que usar um comparador de texto online?
Comparar texto no terminal exige instalar utilitários diff e lidar com flags de linha de comando. Uma ferramenta de diff no navegador elimina completamente esse atrito.
Casos de uso do diff de texto
Comparação dos Formatos de Saída do Diff
Ferramentas de diff produzem saída em vários formatos. A tabela abaixo resume os mais comuns, o que os gera e quando cada um é útil.
| Formato | Ferramenta / Origem | Descrição |
|---|---|---|
| Unified diff | diff -u / git diff | Prefixes lines with + / - / space; includes @@ hunk headers |
| Side-by-side | diff -y / sdiff | Two columns, changed lines aligned horizontally |
| Context diff | diff -c | Shows changed lines with surrounding context, marked with ! / + / - |
| HTML diff | Python difflib | Color-coded HTML table with inline change highlights |
| JSON Patch | RFC 6902 | Array of add/remove/replace operations on a JSON document |
Como o diff de linhas funciona: o algoritmo LCS
A maioria das ferramentas de diff de linhas, incluindo esta, usa o algoritmo LCS (Longest Common Subsequence — Subsequência Comum Mais Longa). O LCS encontra o maior conjunto de linhas que aparece nos dois textos na mesma ordem relativa, sem exigir que sejam contíguas. As linhas que não fazem parte da LCS são as diferenças reais.
O algoritmo LCS padrão usa programação dinâmica e executa em tempo O(m x n), onde m e n são os números de linhas dos dois textos. Para arquivos grandes, variantes otimizadas como o algoritmo de diff de Myers (usado pelo Git) reduzem isso para O(n + d²), onde d é o número de diferenças, tornando-o rápido quando a maioria das linhas é compartilhada.
Exemplos de Código
Implementações de comparação de texto linha por linha em JavaScript, Python, Go e na linha de comando. Cada exemplo produz saída no estilo unified diff.
// Line-by-line diff using the LCS algorithm
function diffLines(a, b) {
const linesA = a.split('\n')
const linesB = b.split('\n')
// Build LCS table
const m = linesA.length, n = linesB.length
const dp = Array.from({ length: m + 1 }, () => new Array(n + 1).fill(0))
for (let i = 1; i <= m; i++)
for (let j = 1; j <= n; j++)
dp[i][j] = linesA[i-1] === linesB[j-1]
? dp[i-1][j-1] + 1
: Math.max(dp[i-1][j], dp[i][j-1])
// Backtrack to produce diff
const result = []
let i = m, j = n
while (i > 0 || j > 0) {
if (i > 0 && j > 0 && linesA[i-1] === linesB[j-1]) {
result.unshift({ type: 'equal', text: linesA[i-1] }); i--; j--
} else if (j > 0 && (i === 0 || dp[i][j-1] >= dp[i-1][j])) {
result.unshift({ type: 'add', text: linesB[j-1] }); j--
} else {
result.unshift({ type: 'remove', text: linesA[i-1] }); i--
}
}
return result
}
const diff = diffLines("alpha\nbeta\ngamma", "alpha\nbeta changed\ngamma\ndelta")
// → [
// { type: 'equal', text: 'alpha' },
// { type: 'remove', text: 'beta' },
// { type: 'add', text: 'beta changed' },
// { type: 'equal', text: 'gamma' },
// { type: 'add', text: 'delta' }
// ]import difflib
text_a = """alpha
beta
gamma""".splitlines()
text_b = """alpha
beta changed
gamma
delta""".splitlines()
# Unified diff (same format as git diff)
for line in difflib.unified_diff(text_a, text_b, fromfile='a.txt', tofile='b.txt', lineterm=''):
print(line)
# --- a.txt
# +++ b.txt
# @@ -1,3 +1,4 @@
# alpha
# -beta
# +beta changed
# gamma
# +delta
# HTML side-by-side diff
d = difflib.HtmlDiff()
html = d.make_file(text_a, text_b, fromdesc='Original', todesc='Modified')package main
import (
"fmt"
"strings"
)
// Minimal LCS-based line diff
func diffLines(a, b string) {
la := strings.Split(a, "\n")
lb := strings.Split(b, "\n")
m, n := len(la), len(lb)
dp := make([][]int, m+1)
for i := range dp {
dp[i] = make([]int, n+1)
}
for i := 1; i <= m; i++ {
for j := 1; j <= n; j++ {
if la[i-1] == lb[j-1] {
dp[i][j] = dp[i-1][j-1] + 1
} else if dp[i-1][j] >= dp[i][j-1] {
dp[i][j] = dp[i-1][j]
} else {
dp[i][j] = dp[i][j-1]
}
}
}
var result []string
i, j := m, n
for i > 0 || j > 0 {
if i > 0 && j > 0 && la[i-1] == lb[j-1] {
result = append([]string{" " + la[i-1]}, result...)
i--; j--
} else if j > 0 && (i == 0 || dp[i][j-1] >= dp[i-1][j]) {
result = append([]string{"+" + lb[j-1]}, result...)
j--
} else {
result = append([]string{"-" + la[i-1]}, result...)
i--
}
}
for _, line := range result {
fmt.Println(line)
}
}
// Output:
// alpha
// -beta
// +beta changed
// gamma
// +delta# Compare two files with unified diff (3 lines of context) diff -u original.txt modified.txt # Git diff between working tree and last commit git diff HEAD -- file.txt # Git diff between two branches git diff main..feature -- src/ # Side-by-side diff in the terminal diff -y --width=120 original.txt modified.txt # Color-coded diff (requires colordiff) diff -u original.txt modified.txt | colordiff