Comparador de Textos
Compara dos textos lado a lado y resalta las diferencias línea por línea
Texto A
Texto B
¿Qué es Text Diff?
Un text diff (abreviatura de "difference", diferencia) es el resultado de comparar dos bloques de texto e identificar qué líneas fueron añadidas, eliminadas o dejadas sin cambios. El concepto tiene su origen en la utilidad Unix diff, publicada por primera vez en 1974 como parte de Version 5 Unix. Hoy en día, el text diff es la base de los sistemas de control de versiones como Git, donde cada commit almacena un diff en lugar de una copia completa de cada archivo.
Un algoritmo de diff encuentra la Subsecuencia Común más Larga (LCS) entre dos secuencias de líneas. Las líneas presentes en el LCS se marcan como sin cambios. Las líneas del texto original que no están en el LCS se marcan como eliminadas. Las líneas del texto modificado que no están en el LCS se marcan como añadidas. El resultado es el conjunto mínimo de cambios necesarios para transformar un texto en el otro.
La salida del diff existe en varios formatos. El unified diff (el predeterminado para git diff) prefija las líneas eliminadas con un signo menos y las líneas añadidas con un signo más. El diff lado a lado organiza ambos textos en columnas paralelas. Esta herramienta usa comparación línea por línea con salida codificada por colores: verde para adiciones, rojo para eliminaciones y neutro para líneas sin cambios. Las líneas sin cambios se muestran sin prefijo por defecto, pero pueden ocultarse para centrarse solo en lo que cambió.
¿Por qué usar una herramienta de diff de texto online?
Comparar texto en un terminal requiere instalar utilidades diff y manejar opciones de línea de comandos. Una herramienta diff en el navegador elimina ese obstáculo por completo.
Casos de uso del diff de texto
Comparativa de formatos de salida diff
Las herramientas de diff producen salida en varios formatos. La tabla siguiente resume los más comunes, qué los genera y cuándo es útil cada uno.
| Formato | Herramienta / Fuente | Descripción |
|---|---|---|
| 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 |
Cómo funciona el diff de líneas: el algoritmo LCS
La mayoría de las herramientas de diff de líneas, incluida esta, usan el algoritmo de Subsecuencia Común más Larga (LCS). El LCS encuentra el mayor conjunto de líneas que aparecen en ambos textos en el mismo orden relativo, sin necesidad de que sean contiguas. Las líneas que no están en el LCS son las diferencias reales.
El algoritmo LCS estándar usa programación dinámica y se ejecuta en tiempo O(m x n), donde m y n son los recuentos de líneas de los dos textos. Para archivos grandes, variantes optimizadas como el algoritmo de diff de Myers (usado por Git) lo reducen a O(n + d^2), donde d es el número de diferencias, lo que lo hace rápido cuando la mayoría de las líneas son compartidas.
Ejemplos de código
Implementaciones de comparación de texto línea por línea en JavaScript, Python, Go y la línea de comandos. Cada ejemplo produce salida en formato 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