diff是unix系統的乙個很重要的工具程式。
它用來比較兩個文字檔案的差異,是**版本管理的基石之一。你在命令列下,輸入
$ diff 《變動前的檔案》 《變動後的檔案》
diff就會告訴你,這兩個檔案有何差異。它的顯示結果不太好懂,下面我就來說明,如何讀懂diff。
diff和patch是一對工具,在數學上來說,diff是對兩個集合的差運算,patch是對兩個集合的和運算。
diff比較兩個檔案或檔案集合的差異,並記錄下來,生成乙個diff檔案,這也是我們常說的patch檔案,即補丁檔案。
patch能將diff檔案運用於原來的兩個集合之一,從而得到另乙個集合。舉個例子來說檔案a和檔案b,經過diff之後生成了補丁檔案c,那麼著個過程相當於 a -b = c ,那麼patch的過程就是b+c = a 或a-c =b。
因此我們只要能得到a, b, c三個檔案中的任何兩個,就能用diff和patch這對工具生成另外乙個檔案。
由於歷史原因,diff有三種格式:
* 正常格式(normal diff)
* 上下文格式(contextdiff)
* 合併格式(unifieddiff)
我們依次來看。
為了便於講解,先新建兩個示例檔案。
第乙個檔案叫做f1,內容是每行乙個a,一共7行。
a
a a
a a
a a
第二個檔案叫做f2,修改f1而成,第4行變成b,其他不變。
a
a a
b a
a a
三、正常格式的diff
現在對f1和f2進行比較
$ diff f1 f2
這時,diff就會顯示正常格式的結果:
4c4
< a
---> b
第一行是乙個提示,用來說明變動位置。它分成三個部分:前面的"4",表示f1的第4行有變化;中間的"c"表示變動的模式是內容改變(change),其他模式還有"增加"(a,代表addition)和"刪除"(d,代表deletion);後面的"4",表示變動後變成f2的第4行。
4c4
第二行分成兩個部分。前面的小於號,表示要從f1當中去除該行(也就是第4行),後面的"a"表示該行的內容。
< a
第三行用來分割f1和f2。
---
第四行前面的大於號表示f2增加了該行,後面的"b"表示該行的內容。
> b
最早的unix(即at&t版本的unix),使用的就是這種格式的diff。
上個世紀80年代初,加州大學伯克利分校推出bsd版本的unix時,覺得diff的顯示結果太簡單,最好加入上下文,便於了解發生的變動。因此,推出了上下文格式的diff。
它的使用方法是加入c引數(代表context)。
$ diff -c f1 f2
顯示結果如下:
*** f1 2012-08-2916:45:41.000000000 +0800
--- f2 2012-08-2916:45:51.000000000 +0800
***************
*** 1,7 ****aa
a!aaa
a--- 1,7 ----aa
a!baa
a
這個結果分成四個部分。
第一部分的兩行,顯示兩個檔案的基本情況:檔名和時間資訊。
*** f1 2012-08-2916:45:41.000000000 +0800
--- f2 2012-08-29 16:45:51.000000000 +0800
"***"表示變動前的檔案,"---"表示變動後的檔案。
第二部分是15個星號,將檔案的基本情況與變動內容分割開。
***************
第三部分顯示變動前的檔案,即f1。
*** 1,7 ****aa
a!aaa
a
這時不僅顯示發生變化的第4行,還顯示第4行的前面三行和後面三行,因此一共顯示7行。所以,前面的"*** 1,7 ****"就表示,從第1行開始連續7行。
另外,檔案內容的每一行最前面,還有乙個標記位。如果為空,表示該行無變化;如果是感嘆號(!),表示該行有改動;如果是減號(-),表示該行被刪除;如果是加號(+),表示該行為新增。
第四部分顯示變動後的檔案,即f2。
--- 1,7 ----aa
a!baa
a
除了變動行(第4行)以外,也是上下文各顯示三行,總共顯示7行。
如果兩個檔案相似度很高,那麼上下文格式的diff,將顯示大量重複的內容,很浪費空間。2023年,gnu diff率先推出了"合併格式"的diff,將f1和f2的上下文合併在一起顯示。
它的使用方法是加入u引數(代表unified)。
$ diff -u f1 f2
顯示結果如下:
--- f1 2012-08-2916:45:41.000000000 +0800
+++ f2 2012-08-2916:45:51.000000000 +0800
@@ -1,7 +1,7 @@aa
a-a+ba
aa
它的第一部分,也是檔案的基本資訊。
--- f1 2012-08-2916:45:41.000000000 +0800
+++ f2 2012-08-29 16:45:51.000000000 +0800
第二部分,變動的位置用兩個@作為起首和結束。
@@ -1,7 +1,7 @@
前面的"-1,7"分成三個部分:減號表示第乙個檔案(即f1),"1"表示第1行,"7"表示連續7行。合在一起,就表示下面是第乙個檔案從第1行開始的連續7行。同樣的,"+1,7"表示變動後,成為第二個檔案從第1行開始的連續7行。
第三部分是變動的具體內容。
aaa
-a+baa
a
除了有變動的那些行以外,也是上下文各顯示3行。它將兩個檔案的上下文,合併顯示在一起,所以叫做"合併格式"。每一行最前面的標誌位,空表示無變動,減號表示第乙個檔案刪除的行,加號表示第二個檔案新增的行。
版本管理系統git,使用的是合併格式diff的變體。
$ git diff
顯示結果如下:
diff --git a/f1 b/f1
index 6f8a38c..449b072 100644
--- a/f1
+++ b/f1
@@ -1,7 +1,7 @@aa
a-a+ba
aa
第一行表示結果為git格式的diff。
diff --git a/f1b/f1
進行比較的是,a版本的f1(即變動前)和b版本的f1(即變動後)。
第二行表示兩個版本的git雜湊值(index區域的6f8a38c物件,與工作目錄區域的449b072物件進行比較),最後的六位數字是物件的模式(普通檔案,644許可權)。
index 6f8a38c..449b072 100644
第三行表示進行比較的兩個檔案。
--- a/f1
+++ b/f1
"---"表示變動前的版本,"+++"表示變動後的版本。
後面的行都與官方的合併格式diff相同。
@@ -1,7 +1,7 @@aa
a-a+ba
aa
* diff - wikipedia
* how to read a patch or diff
* how to work with diff representation ingit
Diff的簡單使用
感謝原作者分享!linux的diff功能很強大 diff options oldfile dir newfile dir 常用的選項有 r 比較目錄 u 將差異的檔案輸出到檔案中 例如 diff ru file one file two file diff.diff patch p1 oldhell...
diff和patch簡單使用
上面的兩個資料夾不同之處是前者有乙個aa.txt檔案,另外修改了cpu s3c44b0 cpu.c檔案 一共有這兩處不同,下面來使用diff進行建立補丁包 退到兩者的上一級目錄,執行diff nur u boot 1.3.1 u boot 1.3.0 test.patch 引數解釋 r recurs...
diff演算法 diff演算法介紹
diff演算法的作用 計算出virtual dom中真正變化的部分,並只針對該部分進行原生dom操作,而非重新渲染整個頁面。傳統diff演算法 通過迴圈遞迴對節點進行依次對比,演算法複雜度達到 o n 3 n是樹的節點數,這個有多可怕呢?如果要展示1000個節點,得執行上億次比較。即便是cpu快能執...