用diff命令計算源代碼(如C源碼)差異時忽略註釋的最詳細方法及應用

這裏我準備系統地總結一下這個問題。如果我們要統計一份源碼不同版本之間的差異,當然希望是忽略所有的註釋,我之前也寫過博客文章總結:https://blog.csdn.net/qysh123/article/details/72866251,但是今天發現之前總結的不是很仔細,所以這裏再仔細總結一下,還是基於上次博客中給的例子,這次稍微複雜了一點,假設我有兩個c代碼,分別是a.c和b.c:

a.c:

test

//command
/*1
 *1
*1
 */

1

b.c:

test


//command2

/*2
 *2
*2
 */

12

我們希望diff的時候僅僅返回最後兩行的不同,在ubuntu中我們可以這樣寫:

diff -B --ignore-matching-lines='^\(//\| \*\|\*\|/\*\)' a.c b.c

那麼返回的結果是:

9c11
< 1
---
> 12

說明a文件的第9行需要變到b文件的第11行(這種輸出格式,大傢俱體可以參考這裏:https://www.cnblogs.com/moxiaopeng/articles/4853352.html

那麼這種情況下是正確的,看來我們確實通過--ignore-matching-lines和後面的正則表達式過濾掉了含有註釋的這些行(這些正則的具體規則可以參考我之前的博客:https://blog.csdn.net/qysh123/article/details/72866251)。

但是事情並沒有這麼簡單,如果我們把b變成這樣:

test


//command2

2

/*2
 *2
*2
 */

12

我們依然希望正則表達式能夠把註釋這些的過濾掉,但是這時候返回的結果竟然成了:

3,6c3,10
< //command
< /*1
<  *1
< *1
---
> 
> //command2
> 
> 2
> 
> /*2
>  *2
> *2
9c13
< 1
---
> 12

也就是說這時候我們的正則表達式似乎統統不起作用了!這真的是太反直覺了。其實這裏網友有討論:https://stackoverflow.com/questions/2747091/how-to-ignore-lines-starting-with-a-string-with-diff

However, -I only ignores the insertion or deletion of lines that contain the regular expression if every changed line in the hunk (every insertion and every deletion) matches the regular expression.

In other words, for each non-ignorable change, diff prints the complete set of changes in its vicinity, including the ignorable ones. You can specify more than one regular expression for lines to ignore by using more than one -I option. diff tries to match each line against each regular expression, starting with the last one given.

簡單說,這裏的意思是說,我們用--ignore-matching-lines的時候,diff並不是以行來進行過濾的,而是以它認爲的hunk(代碼塊)來進行過濾的,也就是說它會用正則去匹配某個hunk的每一行開頭,只有改變的每一行開頭都能和正則中的某一些條件匹配上的時候,才能忽略整個hunk。這個真是太反人類了!

在這裏看到了倒數第二個回答,給了我一些啓示:https://stackoverflow.com/questions/2747091/how-to-ignore-lines-starting-with-a-string-with-diff

還是針對上面修改後的b.c,我們如果輸入:

diff -B <(grep -v '^\(//\| \*\|\*\|/\*\)' a.c) <(grep -v '^\(//\| \*\|\*\|/\*\)' b.c)

就可以得到下面的結果:

4c4,8
< 1
---
> 
> 2
> 
> 
> 12

這已經算是比較完美解決我們需求了。在這個基礎上,如果我們想統計有多少行不同,應該怎麼辦呢?

看到了這裏網友的介紹:https://stackoverflow.com/questions/27236891/diff-command-to-get-number-of-different-lines-only/27236972,還是第二個答案比較靠譜(看來StackOverflow的第二個答案才往往是正確答案啊)。

所以我們運行:

diff -B -y --suppress-common-lines <(grep -v '^\(//\| \*\|\*\|/\*\)' a.c) <(grep -v '^\(//\| \*\|\*\|/\*\)' b.c) | wc -l

得到的輸出結果是5,看看上面的一個輸出即能明白5是什麼含義。關於diff不同參數的含義,可以參考這裏:https://www.cnblogs.com/peida/archive/2012/12/12/2814048.html。個人感覺目前已經能夠比較完美地實現我們希望的功能了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章