尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

python-mini-projects Diff_Util:用 Python 复刻 UNIX diff 的极简文件差异比对工具

python-mini-projects Diff_Util:用 Python 复刻 UNIX diff 的极简文件差异比对工具 python-mini-projects Diff_Util用 Python 复刻 UNIX diff 的极简文件差异比对工具【免费下载链接】python-mini-projectsA collection of simple python mini projects to enhance your python skills项目地址: https://gitcode.com/gh_mirrors/py/python-mini-projectsDiff_Util 是 python-mini-projects 仓库中一个对标 UNIXdiff命令行工具的迷你项目它接收两个文件名作为命令行参数按行比对内容差异并用红/绿双色标注“被删除的行”与“新增的行”。读完本篇你将掌握它的完整安装与运行方式、一条命令看懂差异输出的格式约定并能从 diff.py 的 48 行源码中理解“变更方向推断”“逐行比较”和“尾部增补行报告”三个核心实现细节及其适用边界。项目定位与运行前提README 对项目的定义很直接这是一个 UNIXdiff程序的极简克隆minimal clone。diff.py接收两个文件名作为命令行参数比较它们之间的差异。依赖只有一个即用于终端彩色富文本输出的rich版本锁定在 requirements.txt 中rich10.11.0在运行前安装依赖以 diff.py 所在目录为工作目录pip install -r projects/Diff_Util/requirements.txtREADME 将运行方式按操作系统区分为两类。Windows 下python diff.py orignal_file changed_fileLinux / macOS 下源码首行带有#!/usr/bin/env python3shebang且文件带有可执行权限因此支持直接执行注意 README 中参数名orignal_file的拼写与源码变量名一致此处为原文保留./diff.py orignal_file changed_file两个位置参数中第一个被视为“原始文件”original第二个被视为“变更后的文件”changed。当参数不足两个时diff.py 会打印 Usage 提示并以退出码 1 终止if len(sys.argv) 3: print(Usage:) print(\tMust provide two file names as command-line arguments.) print(\tdiff.py orignal_file changed_file) exit(1)官方示例两次运行的输出解读README 给出的示例文件为v1与v2v13 行Bruce Alfred Jasonv25 行Batman Alfred Red Hood Joker Ras Al Ghul运行./diff.py v1 v2后输出为[-] Line 1: Bruce [] Line 1: Batman [-] Line 3: Jason [] Line 3: Red Hood [] Line 4: Joker [] Line 5: Ras Al Ghul输出格式约定如下理解这三条规则即可读懂任意输入下的结果每一处差异占一对或单独一行[-] Line N: ...以红色标注第一个文件original中第 N 行的内容[] Line N: ...以绿色标注第二个文件changed中同一行号的内容内容相同的行如本例第 2 行Alfred被静默跳过不输出。尾部增补行当两文件行数不同时多出来的行会按“较大文件”的符号身份追加报告。本例中v2多出的第 4、5 行Joker、Ras Al Ghul以[]绿色标出。符号方向随参数顺序翻转README 附带的截图见文章开头配图右侧终端还演示了反方向运行./diff.py v2 v1的结果——此时Batman/Joker/Ras Al Ghul等变为红色[-]Bruce/Jason变为绿色[]。也就是说[-]/[]的角色始终跟随命令行参数的顺序而不是文件内容的“新旧”关系。源码剖析四个步骤完成一次 diffdiff.py 全文仅 48 行执行流程可以拆成四步。第一步命令行校验与文件读入在 Usage 校验之后diff.py 将两个参数分别绑定到orignal与changed并用open(..., r).readlines()把两个文件按行读入列表。readlines()会保留每行的换行符这正是后续输出中“原行自带换行、新行紧跟其后”排版效果的来源——源码在打印 original 行时显式使用enddiff.py让行尾原有的\n自然结束该输出行。第二步用行数推断“变更方向”这是本项目最有意思的设计。diff.py 并不预设哪个文件更新而是在 diff.py 中比较两个列表的长度color green symbol f[bold {color}][] # Determine which file has changed much. if len(changed_contents) len(orignal_contents): color red symbol f[bold {color}][-] smallest_sloc, largest_sloc changed_contents, orignal_contents else: smallest_sloc, largest_sloc orignal_contents, changed_contents从源码结构看其逻辑是行数较少的文件被视作“改动删减后的较小版本”行数较多的文件被视作“包含新增内容的较大版本”。symbol与color变量因此被初始化为较大文件一侧的身份绿色[]或红色[-]供第四步报告尾部增补行时复用。这也解释了上一节第 3 条格式规则无论你把哪个文件放在第一个参数位置行数更多的一方始终被标注为“增补”行数更少的一方被标注为“删减”。第三步逐行比较并着色输出核心比较循环在 diff.pyfor line in range(0, len(smallest_sloc)): if orignal_contents[line] changed_contents[line]: # Ignore if the lines are same. continue else: # Display the changes on the respective lines of the files. print(f[bold red][-] Line {line 1}:[/bold red] {orignal_contents[line]}, end ) print(f[bold green][] Line {line 1}:[/bold green] {changed_contents[line]})注意两点实现细节循环边界是len(smallest_sloc)而非两个文件行数的最大值——比较只覆盖到较短文件用尽为止较长文件多出的行留给下一步处理。着色由rich.print的标记语法完成from rich import print覆盖了内置print[bold red]/[bold green]分别渲染加粗红/绿色行号统一采用从 1 计数的line 1与 UNIXdiff的行号习惯一致。第四步报告较大文件的尾部增补行diff.py 把“尾部增补”的报告挂载在循环的最末一次比较上# Show the additions [] or deletions [-] for the file that is the largest. if line len(smallest_sloc) - 1: for new_line in range(line 1, len(largest_sloc)): print(f{symbol} Line {new_line 1}:[/bold {color}] {largest_sloc[new_line]})当比较到较短文件的最后一行line len(smallest_sloc) - 1时内层循环从line 1遍历到较长文件末尾用第二步确定的symbol/color把每一行多出来的内容输出。以./diff.py v1 v2为例循环比较到第 3 行Jason与Red Hood不同时触发该分支随后依次打印[] Line 4: Joker与[] Line 5: Ras Al Ghul与 README 的示例输出完全对应。行为边界它能做什么、不能做什么在引用或依赖该工具前建议明确它的适用前提。以下两点均可从源码直接确认它是“行号对齐”的比对而非真正的编辑距离 diff。循环按行号一一对应line索引直接相等并不计算最长公共子序列因此不会生成 UNIXdiff那样的“hunk”块或最小编辑脚本。README 自称 minimal clone正体现了这一取舍它擅长回答“同一行号上内容改了什么、哪一方多了哪些行”但面对中间插入/删除导致的整体错位时会把错位之后的每一行都报告为差异。尾部增补报告与末行是否相等耦合。从源码结构看增补行输出语句位于“末行内容不同”的else分支内部diff.py。可以推断若较短文件的最后一行恰好与较长文件对应行相同该分支走的是continue则较长文件多出的行将不会被报告。这是复刻版与成熟diff实现之间的一处行为差异在评估输出完整性时需要留意。此外源码与 README 中orignal这一拼写原文如此贯穿变量名、Usage 提示与参数示例阅读源码或排查日志时请按此拼写检索。快速复现指南按以下步骤可在本地完整复现 README 的示例输出进入 projects/Diff_Util 目录执行pip install -r projects/Diff_Util/requirements.txt安装rich10.11.0按上文示例内容创建v13 行与v25 行两个纯文本文件依次运行python diff.py v1 v2与python diff.py v2 v1Linux/macOS 亦可用./diff.py v1 v2对照本文“官方示例”小节的三组输出验证差异行成对出现、相同行静默跳过、尾部增补行按参数顺序着色如需核对某段输出的生成逻辑可按“四步流程”小节中的行号锚点直接定位 diff.py 对应代码段。Diff_Util 用最少的代码展示了终端 diff 工具的完整骨架参数校验、按行数推断变更方向、逐行比较、富文本着色与尾部增补报告。对希望学习命令行参数处理、rich彩色输出以及“先定策略再写循环”这类结构思路的读者它是一份小而完整的阅读材料。【免费下载链接】python-mini-projectsA collection of simple python mini projects to enhance your python skills项目地址: https://gitcode.com/gh_mirrors/py/python-mini-projects创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表