脚本如何比对两份文本差异

wen 实用脚本 27

本文目录导读:

脚本如何比对两份文本差异

  1. 使用Python的difflib
  2. 使用difflib.SequenceMatcher进行精确比较
  3. 使用外部工具(subprocess调用)
  4. 使用第三方库:deepdiff
  5. 实用工具函数:文件对比
  6. 命令行脚本版本
  7. 最佳实践建议

我来介绍几种比对文本差异的常用方法和脚本实现。

使用Python的difflib

基础文本差异比较

import difflib
def compare_texts(text1, text2):
    """比较两段文本的差异"""
    # 将文本按行分割
    lines1 = text1.splitlines()
    lines2 = text2.splitlines()
    # 创建差异比较器
    differ = difflib.Differ()
    diff = list(differ.compare(lines1, lines2))
    return '\n'.join(diff)
# 示例
text_a = """第一行
第二行
第三行
第四行"""
text_b = """第一行
第二行修改
第三行
新增行
第四行"""
result = compare_texts(text_a, text_b)
print(result)

生成HTML格式的差异报告

import difflib
def generate_html_diff(text1, text2):
    """生成HTML格式的差异报告"""
    lines1 = text1.splitlines()
    lines2 = text2.splitlines()
    # 创建HTML差异比较器
    html_diff = difflib.HtmlDiff()
    html = html_diff.make_file(lines1, lines2, 
                               context=True,
                               numlines=3)
    return html
# 保存为HTML文件
html_result = generate_html_diff(text_a, text_b)
with open('diff_report.html', 'w', encoding='utf-8') as f:
    f.write(html_result)

使用difflib.SequenceMatcher进行精确比较

import difflib
def detailed_diff(text1, text2):
    """详细比对文本差异"""
    # 创建SequenceMatcher对象
    matcher = difflib.SequenceMatcher(None, text1, text2)
    # 获取操作码(增删改)
    for tag, i1, i2, j1, j2 in matcher.get_opcodes():
        if tag == 'equal':
            print(f"相同: [{i1}:{i2}] -> [{j1}:{j2}]")
        elif tag == 'insert':
            print(f"新增: [{i1}:{i2}] -> [{j1}:{j2}]: {text2[j1:j2]}")
        elif tag == 'delete':
            print(f"删除: [{i1}:{i2}]: {text1[i1:i2]} -> [{j1}:{j2}]")
        elif tag == 'replace':
            print(f"替换: [{i1}:{i2}]: {text1[i1:i2]} -> [{j1}:{j2}]: {text2[j1:j2]}")
# 更细粒度的字符级别比较
def char_level_diff(text1, text2):
    """字符级别的差异比较"""
    import difflib
    matcher = difflib.SequenceMatcher(None, text1, text2)
    result = []
    for tag, i1, i2, j1, j2 in matcher.get_opcodes():
        if tag == 'equal':
            result.append(text1[i1:i2])
        elif tag == 'insert':
            result.append(f'[+{text2[j1:j2]}]')
        elif tag == 'delete':
            result.append(f'[-{text1[i1:i2]}]')
        elif tag == 'replace':
            result.append(f'[-{text1[i1:i2]}+{text2[j1:j2]}]')
    return ''.join(result)

使用外部工具(subprocess调用)

import subprocess
import tempfile
import os
def diff_with_tool(text1, text2, tool='diff'):
    """使用外部差异工具"""
    # 创建临时文件
    with tempfile.NamedTemporaryFile(mode='w', delete=False) as f1:
        f1.write(text1)
        temp1 = f1.name
    with tempfile.NamedTemporaryFile(mode='w', delete=False) as f2:
        f2.write(text2)
        temp2 = f2.name
    try:
        # 调用外部diff命令
        if tool == 'diff':
            result = subprocess.run(['diff', temp1, temp2], 
                                  capture_output=True, text=True)
        elif tool == 'diff-u':
            result = subprocess.run(['diff', '-u', temp1, temp2], 
                                  capture_output=True, text=True)
        elif tool == 'wdiff':
            result = subprocess.run(['wdiff', temp1, temp2],
                                  capture_output=True, text=True)
        return result.stdout
    finally:
        # 清理临时文件
        os.unlink(temp1)
        os.unlink(temp2)
# 使用示例
diff_result = diff_with_tool(text_a, text_b, 'diff-u')
print(diff_result)

使用第三方库:deepdiff

pip install deepdiff
from deepdiff import DeepDiff
import json
def compare_structured_text(text1, text2):
    """比较结构化文本(如JSON)"""
    # 如果是JSON
    try:
        obj1 = json.loads(text1)
        obj2 = json.loads(text2)
        diff = DeepDiff(obj1, obj2, verbose_level=2)
        return diff.to_json(indent=2)
    except:
        return "非JSON格式,请使用其他方法"
# 示例
json_a = '{"name": "张三", "age": 30, "city": "北京"}'
json_b = '{"name": "张三", "age": 31, "city": "上海"}'
result = compare_structured_text(json_a, json_b)
print(result)

实用工具函数:文件对比

import difflib
import os
def compare_files(file1, file2, output_format='text'):
    """对比两个文件的差异"""
    # 读取文件
    with open(file1, 'r', encoding='utf-8') as f:
        text1 = f.read()
    with open(file2, 'r', encoding='utf-8') as f:
        text2 = f.read()
    if output_format == 'text':
        # 文本格式
        differ = difflib.Differ()
        diff = list(differ.compare(text1.splitlines(), text2.splitlines()))
        return '\n'.join(diff)
    elif output_format == 'html':
        # HTML格式
        html_diff = difflib.HtmlDiff()
        return html_diff.make_file(text1.splitlines(), text2.splitlines())
    elif output_format == 'unified':
        # 统一格式
        return '\n'.join(difflib.unified_diff(
            text1.splitlines(), text2.splitlines(),
            fromfile=os.path.basename(file1),
            tofile=os.path.basename(file2)
        ))
# 使用示例
result = compare_files('file1.txt', 'file2.txt', 'unified')
print(result)

命令行脚本版本

#!/usr/bin/env python3
# diff_compare.py
import sys
import difflib
import argparse
def main():
    parser = argparse.ArgumentParser(description='文本差异比较工具')
    parser.add_argument('file1', help='第一个文件')
    parser.add_argument('file2', help='第二个文件')
    parser.add_argument('-f', '--format', choices=['text', 'html', 'unified'],
                       default='text', help='输出格式')
    parser.add_argument('-o', '--output', help='输出文件路径')
    args = parser.parse_args()
    # 读取文件
    with open(args.file1, 'r', encoding='utf-8') as f:
        text1 = f.read()
    with open(args.file2, 'r', encoding='utf-8') as f:
        text2 = f.read()
    lines1 = text1.splitlines()
    lines2 = text2.splitlines()
    # 生成差异
    if args.format == 'html':
        result = difflib.HtmlDiff().make_file(lines1, lines2)
    elif args.format == 'unified':
        result = '\n'.join(difflib.unified_diff(lines1, lines2))
    else:
        result = '\n'.join(difflib.Differ().compare(lines1, lines2))
    # 输出
    if args.output:
        with open(args.output, 'w', encoding='utf-8') as f:
            f.write(result)
    else:
        print(result)
if __name__ == '__main__':
    main()

使用方式:

python diff_compare.py file1.txt file2.txt -f unified

最佳实践建议

  1. 根据场景选择方法

    • 简单文本对比:difflib.Differ()
    • 版本控制风格:unified_diff()
    • 可视化展示:HTML格式
    • 结构化数据:deepdiff
  2. 性能优化

    • 大文件使用流式处理
    • 必要时使用快速算法(如hash比较)
  3. 编码处理

    • 始终指定正确的编码
    • 处理不同换行符(\r\n vs \n)

这些方法可以覆盖大部分文本差异比较的需求,需要根据具体使用场景选择最合适的方式。

抱歉,评论功能暂时关闭!