diff詳解,讀懂diff結果

薰衣草的旋律發表於2016-08-22

1.概述

本文將要討論的是diff命令,diff用來比較兩個檔案。當然檔案比較的工具很多,windows系統下面就有不錯的工具可以使用,例如常用的Beyond Compare,WinMerge都是圖形介面的比較工具而且使用非常方便,如果你僅僅是在windows下工作,這些GUI的比較工具絕對是首選。對於在linux環境下工作的人來說,如果每次想看兩個檔案的區別都要將檔案下載到windows環境然後用圖形工具進行比較實在是太麻煩了。那麼我們必須學會使用linux環境下的比較工具diff。

2.diff如何工作,如何理解diff的執行結果

diff分析兩個檔案,並輸出兩個檔案的不同的行。diff的輸出結果表明需要對一個檔案做怎樣的操作之後才能與第二個檔案相匹配。diff並不會改變檔案的內容,但是diff可以輸出一個ed指令碼來應用這些改變。
現在讓我們來看一下diff是如何工作的,假設有兩個檔案:

//file1.txt
I need to buy apples.
I need to run the laundry.
I need to wash the dog.
I need to get the car detailed.

//file2.txt
I need to buy apples.
I need to do the laundry.
I need to wash the car.
I need to get the dog detailed.

我們使用diff比較他們的不同:
diff file1.txt file2.txt

輸出如下結果:
2,4c2,4
< I need to run the laundry.
< I need to wash the dog.
< I need to get the car detailed.
---
> I need to do the laundry.
> I need to wash the car.
> I need to get the dog detailed.

我們來說明一下該輸出結果的含義,要明白diff比較結果的含義,我們必須牢記一點,diff描述兩個檔案不同的方式是告訴我們怎麼樣改變第一個檔案之後與第二個檔案匹配。我們看看上面的比較結果中的第一行 2,4c2,4 前面的數字2,4表示第一個檔案中的行,中間有一個字母c表示需要在第一個檔案上做的操作(a=add,c=change,d=delete),後面的數字2,4表示第二個檔案中的行。

2,4c2,4 的含義是:第一個檔案中的第[2,4]行(注意這是一個閉合區間,包括第2行和第4行)需要做出修改才能與第二個檔案中的[2,4]行相匹配。
接下來的內容則告訴我們需要修改的地方,前面帶 < 的部分表示左邊檔案的第[2,4]行的內容,而帶> 的部分表示右邊檔案的第[2,4]行的內容,中間的 --- 則是兩個檔案內容的分隔符號。

3.Normal模式

上面的部分我們說明了如何檢視diff命令的結果,實際上對於上面的比較,我們使用的是diff命令的Normal模式,這也是diff命令的預設模式,也就是說diff兩個檔案的時候如果不加模式引數則是預設模式進行比較,其效果與(--normal)一樣,我們舉一些例子來說明Normal模式下的輸出結果(前面已經說明了一種比較結果),為了直觀檢視兩個檔案的不同我在windows下面通過BeyondCompare工具列出兩個檔案的不同,而截圖下面的黑色部分則是diff的比較輸出截圖。

第一個檔案比第二個檔案少了行的情況:

第一個檔案比第二個檔案多出行的情況:

2

第一個檔案與第二個檔案不相同的情況:

3

以上diff命令執行的時候沒有指定額外的模式引數,所以其使用的是預設的Normal模式,效果與新增命令列引數--normal 是一樣的。

4.Context模式

預設情況下的模式輸出結果實際上是符合計算機的思維方式,不太直觀,所以其輸出結果並不能夠很好的被人理解,diff命令除了預設模式之外還提供了另外兩種模式,Context和Unified模式,本節我們說說如何查閱Context模式下的輸出結果。diff命令應用Context模式只需要新增命令列引數 diff -c  即可,我們先看看兩個案例檔案:

33

接下來說明這兩個檔案以diff  -c 方式比較的結果:

3

5.Unified模式

diff還有一種比較方式,也即Unified模式,使用命令列 –u 來執行該模式的比較。其比較結果與Context模式很像,但是簡化了一些輸出,我們看看我們的案例檔案,與上面的一樣:

3

使用diff –u 比較的結果:

3

可以看到其比較結果與Context模式實際上差不多,只不過將比較結果合併到一起了。

6.比較目錄

使用diff可以比較兩個目錄,其比較格式是  diff  directory1  directory2 檢視如下目錄比較結果:

3

比較兩個目錄的時候無非是有的檔案僅僅存在於某個目錄中而在另一個目錄中沒有,如果存在同名的檔案,則比較這兩個檔案的不同。diff比較目錄的結果我們可以結合grep命令篩選出我們想要的輸出,例如僅僅輸出兩個目錄下不同的檔案而忽略掉某一個目錄獨有另一個目錄不存在的輸出記錄。

另外比較目錄的時候有兩個引數很有用,-r 和 -q  ,前者表示遞迴比較目錄中的子目錄,後者表示僅僅列出兩個目錄中有哪些檔案不同,而不去比較目錄中各個檔案的具體內容。特別是在作版本控制的時候,比較的兩個目錄如果檔案很多,我們可能只需要知道兩個目錄有那些檔案有差異就行了,而不需要diff列出具體的差異內容,因為檔案很多,預設情況下diff會輸出兩個目錄所有不同檔案的內容差異,這會使得輸出很多很雜亂,加上-q之後則只會輸出不同的檔名。

diff -r -q directory1 direcotory2

7.一些有用的引數

diff還提供了一些有用的引數來控制比較行為與輸出結果,一些常用的引數如下:
-b  --ignore-space-change 忽略空格,如果兩行進行比較,多個連續的空格會被當作一個空格處理,同時會忽略掉行尾的空格差異。
-w --ignore-all-space 忽略所有空格,忽略範圍比-b更大,包括很多不可見的字元都會忽略。
-B 忽略空白行。
-y  輸出兩列,一個檔案一列,有點類似GUI的輸出外觀了,這種方式輸出更加直觀。
-W 大寫W,當指定-y的時候設定列的寬度,預設是130
-x, --exclude=PAT 比較目錄的時候排除指定PAT模式的檔名的比較
-i, --ignore-case 忽略兩個檔案中大小寫的不同
-e 將比較的結果儲存成一個ed指令碼,之後ed程式可以執行該指令碼檔案,從而將file1修改成與file2的內容相同,這一般在patch的時候有用。
-r 如果比較兩個目錄,-r引數會比較其下同名的子目錄
-q 輸出結果中,只指出兩個檔案不同,而不輸出兩個檔案具體內容的比較,這在比較兩個目錄的時候很好用。我們只需要知道兩個目錄下那些檔案做了修改,而不需要知道每個檔案具體修改了那些內容。特別是當兩個目錄檔案很多的時候。

diff  -e  1.txt  2.txt  > script.txt
這樣就是生成了一個ed可以執行的指令碼檔案script.txt,生成指令碼檔案之後我們還需要做一個操作, 在指令碼檔案末尾新增ed的write指令,只需要執行 echo "w" >>script.txt 將w指令附加到指令碼檔案的最後一行即可。
那麼如何應用該指令碼檔案呢,可以這樣使用:
ed  -  1.txt < script.txt
注意中間的 – 符號表示從標準輸入中讀取,而 < script.txt 則重定向script.txt的內容到標準輸入。這樣執行之後1.txt的內容將與2.txt完全相同。

 

如果您覺得這篇文章對您有幫助,需要您的【贊】,讓更多的人也能看見哦

相關文章