diff与patch,diff的三种模式说明
一个简单的文件比较
file1
1
2
3
4
file2
2
3
4
5
先从简单的说起:
- -c 显示全部内文(context diff),并标出不同之处。
diff -c file1 file2
*** 1f 2016-03-19 14:49:39.881834600 +0800
--- 2f 2016-03-19 14:50:16.096849181 +0800
***************
*** 1,4 ****
- 1
2
3
4
--- 1,4 ----
2
3
4
+ 5
输出文件很易理解
- -u 以合并的方式(unified diff)来显示文件内容的不同
diff -u file1 file2
--- file1.txt 2016-03-16 21:49:25.282579534 +0800
+++ file2.txt 2016-03-18 15:53:35.214591623 +0800
@@ -1,4 +1,4 @@
-1
2
3
4
+5
第一部分,也是文件的基本信息:
“—”表示变动前的文件,”+++”表示变动后的文件。
第二部分,变动的位置用两个@作为起首和结束
前面的”-1,4”分成三个部分:减号表示第一个文件,”1”表示第1行,”4”表示连续4行。合在一起,就表示下面是第一个文件从第1行开始的连续4行。同样的,”+1,4”表示变动后,成为第二个文件从第1行开始的连续4行。
- 比较复杂的就是正常模式(normal diff)的比较了
1d0
< 1
4a4
> 5
在解释上述指令之前,先来谈谈我理解的diff对处理文件的想法
- 对于两个较为相似的文本来说,经过替换,增加,删除一定能变成另外一个文本
- 当得知一个文本变成另外一个文本的方式,这个过程也是可逆的,即你同时也知道了相反的转变方法
正常模式就是来详述这一方式的
为什么是需要三个方法呢,替换、增加、删除感觉有重复啊?
diff重点是为了找出两个文件的差异,根据差异来修改,而不是简单复制或者大规模替换,因此是三个步骤
也可以说是两个,为什么呢?
来说一下diff 正常模式下可能出现的三个表达形式(r1,r2分别代表第一个,第二个文件的行数,可能是多行)
- r1cr2 c为change
- r1dr2 d为delete
- r1ar2 a为add
- <>分别代表1,2文本
diff file1 file2
是给出了file1到file2的变换方法,同时也给出了file2到file1的方法
理解上述指令为
- r1与r2的内容互换
- r1的文本删掉,放到r2的位置上来,含义是以前r2上方的文本(包括r2)向上移动,给新文本的位置
- 与前一个类似,r2文本删掉,放到r1的位置,方法同上
可能会注意到我描述的方法与c,d,r的含义不同,这是因为c,d,r是站在第一个文本的角度上说的,而我两个文本一起而言的。
其实这样看来,2,3方法本质是一样的,所以可以看做是两种方法,移动和替换。
再强调一次,按照diff产生的结果做下去,两个文本内容替换
可以通过上述简单的例子验证
还有要特别注意的是,操作的方法
增加和删除都是最后的结果,并不是过程,每一步的操作均只针对原文本,而不是改动后的
一个稍微复杂的例子
file1内容为
a d z e g z
file2内容为
e d g g e z z f
diff file1 file2
1,3d0
< a
< d
< z
4a2
> d
5a4,6
> g
> e
> z
6a8
> f
建议试试上述过程,看结果是否正确
如果失败了,可以跟着我走一次此过程
- 1,3d0 将a-z删除并添加到file2上,结果为 a d z (e g z), (a d z e d g g e z z f)
- 4a2 删除file2的d并放到file1的第四行,结果为 a d z (e d g z), (a d z e) d (g g e z z f)
- 5a4,6 删除file2的4-6放到file1的第五行,结果为 a d z (e d g g e z z), (a d z e) d (g) g e z (z f)
- 6a8, 删除file2的8放到file的第六行,结果为 a d z (e d g g e z z f), (a d z e) d (g) g e z (z) f
对下列过程说明:
- 为了表示每一步仍是在原文本上的改动,因此并没有删掉原文本,移动行数可对照原文本行数观察
- 括号内为每一步产生的结果
如果你认为每一步可以拆分分别执行,可以先将diff结果输出保存,之后将文本分解,使用patch执行每一步操作看看最终结果是否正确
关于patch与diff的一点说明
这里只讨论简单的patch文件使用
diff file1 file2 | patch
不可执行
diff -u file1 file2 | patch
可执行
为什么呢?
很简单,后者的diff中有对应的file1,file2,将其文件置于其他目录下,就无法执行了
如果只把file1移走呢?
会出现
Reversed (or previously applied) patch detected! Assume -R? [n]
输y的话就把file2的内容变成file1,正是逆操作(虽然是-u,但对于normal模式依旧试用)