diff程序是linux上非常重要的工具,用于比较文件的内容,特别是比较两个版本不同的文件(本文中的a.c、b.c可以理解为两个版本的同一个文件,b.c是在a.c的基础上的修正版)以找到改动的地方。diff在命令行中打印每一个行的改动。最新版本的diff还支持二进制文件。diff程序的输出被称为补丁(patch),因为unix系统中还有一个patch程序,可以根据diff的输出将a.c的文件内容更新为b.c。diff是svn、cvs、git等版本控制工具不可或缺的一部分。
下面用一个实例来讲述diff和patch的使用。
文件a.c的内容如下:
#include <stdio.h> int main(int argc, char *argv[]) { // add code here return 0; } |
文件b.c的内容如下:
#include <stdio.h> int main(int argc, char *argv[]) { printf("Hello world"); return 0; } |
执行命令:
diff a.c b.c > b.patch |
输出b.patch的内容如下:
5c5 < // add code here --- > printf("Hello world"); |
接着执行下面的命令就可以将patch文件b.patch应用于a.c文件上,将a.c文件的内容更新为新的版本(即b.c)
patch a.c b.patch |
a.c的内容被更新为b.c的内容:
#include <stdio.h> int main(int argc, char *argv[]) { printf("Hello world"); return 0; } |
不过,diff的输出让人读起来很废劲,因为这个输出本来就不是给人看的,如果你知道一点关于ed编辑器的用法,就容易理解了。最开始的时候diff的输出不是这种格式的,后来受到ed编辑器的影响才变成这个样子,至于其发展历程请移步维基百科,因此在解释diff的输出之前,先简单介绍一下ed编辑器。
ed是一个交互式的文本编辑器,类Unix系统中有很多很神奇的编辑器,号称神器的有vi、vim、emacs,还有常规意义的编辑器nano、gedit,还有看起来很诡异的sed(Stream Editor)、awk,ed这是另一个很诡异的编辑器,不同于前面的任何一种。
打开shell,按次序输入如下的命令(需要一句一句的敲):
touch c.c ed c.c 0a #include <stdio.h> int main(int argc, char *argv[]) { // add code here return 0; } . w q |
使用cat命令查看c.c,该文件的内容就是上面代码中“0a”和“.”之前代码。
和vim一样,ed通过一系列的命令来编辑文件:
ed编辑器的好处在于可以将一系列命令写成一个文件,然后进行批量执行。比如需要在所有的源代码开头加上版权信息,则可以编写如下的ed文件,保存为add_header:
0a /** * © 2012 zhlwish.com */ . w q |
然后写一段shell脚本对源代码文件进行遍历,对每个代码执行如下代码即可批量对源代码文件添加版权信息:
ed a.c < add_header |
关于ed的命令和其他方法请参考Unix ed Editor Command Set本文不详述。
diff的输出格式是对ed脚本(ed script)的一种扩展,遵循ed的命令语法,添加了”<”和”>”分别用于表示新文件的内容和旧文件的内容,比如前文中diff的输出可以按如下方式理解:
当然还有更复杂的情况,如“3c3,6”、“6d8”,前者表示旧版本文件中的第3行被修改,对应新文件中的第3-6行,后者表示旧版本文件的第6行被删除,在新文件中是第8行。
可以通过参数指定diff输出格式,有兴趣的笔者可以分别进行尝试:
除以上选项外,diff的有用的选项还包括:
因为成文仓促,不免有不对之处,敬请读者指正。(全文完)