The Differnet diff

diff是一个不被重视的命令,不被重视是因为所有人都觉得它很简单,都觉得没有什么可以研究的,但是事实并非如此。
一般情况下,diff的输出是不便阅读的,例如
$diff diff.txt diff.info
2c2
<  the info  is  about diff
---
>
3a4
>   **********************
7c8
<  diff OPTIONS... FILES...  <-  usage
---
>  diff OPTIONS... FILES...
14c15
<  (it isn ' t simple)If one file is a directory and the other is not, `diff '  compares the
---
>  If one file  is  a directory and the other  is  not, `diff '  compares the

 那么如何让diff的输出更加易读呢,可以使用-y参数
$diff -yt diff.txt diff.info
File: diff.info,  Node: Invoking diff,  Next: Invoking diff3,      File: diff.info,  Node: Invoking diff,  Next: Invoking diff3,

the info is about diff                                          |
13 Invoking `diff'                                                 13 Invoking `diff'
                                                                >  **********************

The format for running the `diff' command is:                      The format for running the `diff' command is:

diff OPTIONS... FILES... <- usage                               |  diff OPTIONS... FILES...

In the simplest case, two file names FROM-FILE and TO-FILE are     In the simplest case, two file names FROM-FILE and TO-FILE are
given, and `diff' compares the contents of FROM-FILE and TO-FIL    given, and `diff' compares the contents of FROM-FILE and TO-FIL

file name of `-' stands for text read from the standard input.     file name of `-' stands for text read from the standard input.

special case, `diff - -' compares a copy of standard input to i    special case, `diff - -' compares a copy of standard input to i


(it isn't simple)If one file is a directory and the other is no |  If one file is a directory and the other is not, `diff' compare

file in the directory whose name is that of the non-directory.     file in the directory whose name is that of the non-directory.

non-directory file must not be `-'.                                non-directory file must not be `-'.
这种side by side的效果就比较方便了。
掌握了diff的简单参数对于使用cvs命令行的人是个福音,因为在cvs diff的时候,也是可以制定这些参数的,这样在看两个版本的代码的时候就很方便了
diff的高级功能
diff在如何显示结果的问题上面,为用户提供了很大的定制空间。下面我们就让diff的输出有颜色,至少可以达到windiff的效果
对于如何在终端上面显示颜色的问题,可以参考我的 另外一篇博客
diff提供了几个选项
-- line - format
-- new - line - format
-- old - line - format
-- unchanged - line - format
-- old - group - format
-- new - group - format
-- changed - group - format
-- unchanged - group - format
几个选项的具体含义可以参考diff的info。
下面我们就如此定制一下diff的输出
$diff  -- old - line - format = ' ^[[1;31;47m<^[[1;31;40m %l^[[m
'
 --new-line-format= ' ^ [[ 1 ; 33 ;44m >^ [[ 1 ; 33 ;40m  % l ^ [[m
'  --unchanged-line-format= ' ^ [[ 1 ;32m =   % l ^ [[m
'  diff.txt diff.info
输出效果如下

这样的输出还是很漂亮的吧
而且这样指定输出格式的选项可以完全的使用在cvs diff当中的哦

side by side的更漂亮的diff
在windows下面有很多很好的diff工具,像windiff和ultra edit里面的diff根本就不友好,效果也很烂,一块红一块黄的,看着很伤眼睛。
windows下面最好的diff工具,我认为是beyond compare,简称bc。
但是在×nix下面,情况是如何呢?我在linux里面,一直使用vimdiff,效果也是很不错的,几乎可以达到一个字符界面的工具能达到的顶峰了。
不过vimdiff有一个问题是和cvs结合不够紧密,如果想在执行cvsdiff之后能够自动弹出一个vimdif的界面,是需要有一些插件支持的。
那么怎么办呢?其实我们可以继续从diff自身挖掘出新的东西来。
上面说的,使用-y参数可以是diff的输出成为左右两列,对比两个版本,我们就以这个为基础,结合awk,sed等工具,以及term对颜色的支持,实现vimdiff中能够达到的效果。
下面就是一个效果的截图

怎么样,还是很炫的吧。
其实达到这个效果哦很容易,下面就是脚本cdiff的内容
  1 #!/bin/bash
  2 [[ $# > 0 ]] && width=$1 || width=130
  3 ((halfWidth=width/2))
  4 ((sepIndex=halfWidth -1 ))
  5 colorEnd="/033[m"
  6 missing="/033[1;34;46m"
  7 changedLeft="/033[1;37;45m"
  8 changedRight="/033[1;33;45m"
  9 orphan="/033[1;37;44m"
 10 common="/033[1;32;40m"
 11 sep=^A
 12 input=-
 13 cat $input|sed "s/^/(./{$sepIndex/}/)/(./)//1$sep/2$sep/"|awk -F$sep -f <(echo '
 14 $2=="|" {printf '/"$changedLeft%s$colorEnd%s$changedRight%-${halfWidth}s$colorEnd//n/"', $1, $2, $3}
 15 $2==">" {gsub(// /,"-",$1); printf '/"$missing%s$colorEnd%s$orphan%-${halfWidth}s$colorEnd//n/"', $1, $2, $3}
 16 $2=="<" {
 17     # fill $3 with "-"
 18     $3="  ---------------------------------------------------------------------------"
 19     printf '/"$orphan%s$colorEnd%s$missing%-${halfWidth}s$colorEnd//n/"', $1, $2, substr($3, 0, '$halfWidth')
 20 }
 21 $2==" " {printf '/"$common%s%s$common%-${halfWidth}s$colorEndn//n/"', $1, $2, $3}
 22 ')
 23
不过,美中不足,就是还不能实现对一行中单词的比较,对有区别的单词进行高亮,完全达到vimdiff和bc的效果。

现在就把整个的代码都贴出来,这个脚本名为cdiff,就是colorful diff的意思
可以支出如下的几种用法
cdiff file1 file2, cat file1 |cdiff - file2 , 效果如图一
cdiff -y file1 file2 ,diff -y file1 file2 |cdiff,效果如图二
cvs diff file |cdiff,效果如下

代码在这里
   1 #!/bin/bash
  2 usage()
  3 {
  4     
echo  "$0 [-w <width>] [file1] [file2]"
  5 }
  6 defaultWidth=125 # default output width of diff -y
  7 width=$defaultWidth
  8
  9 # get the options, just 
if  -y and -W specified
 10 columnOutput=0
 11 while getopts 
:yW : options
 12 
do
 13     case $options in
 14     y)columnOutput=1;;
 15     W)width=$OPTARG;;
 16     ?);;
 17     esac
 18 done
 19 
if  [[ $OPTIND -gt $# ]] ; then
 20     # no filename, therefore the input from pipe, and the input is must be a output of diff -y
 21     diffInput=1
 22     columnOutput=1
 23 
else
 24     file1=$$OPTIND
 25     [[ $# -gt `expr $OPTIND + 1` ]] && file2=$`expr $OPTIND + 2` || file2=-
 26     [[ $# -gt `expr $OPTIND + 2` ]] && 
echo  "Warning: too many files to be compared" >&2
 27 fi
 28
 29 
if  [[ $columnOutput -eq 1 ]]; then
 30     ((halfWidth=width /2))
 31     ((sepIndex=halfWidth -1 ))
 32     colorEnd="[m"
 33     missing="[1;34;46m"
 34     changedLeft="[1;37;45m"
 35     changedRight="[1;33;45m"
 36     orphan="[1;37;44m"
 37     common="[1;32;40m"
 38     nondiff="[1;31;40m"
 39     sep="^A"
 40     # in order to compatible with output cvs diff, which contain some lines that isn't in diff -y 
format
 41     # we need to judge which lines is in diff 
format
 42     ([[ $diffInput -eq 1 ]] && cat - || diff "$@" -y )|expand|
 43         sed "s/^(.{$sepIndex}) ([ ><|])/$sep$sep/"|awk -F$sep -f <(
echo  '
 44     $2=="|" {printf '"$changedLeft%s$colorEnd %s$changedRight%-${halfWidth}s$colorEnd/n"', $1, $2, $3}
 45     $2==">" {gsub(/ /,"-",$1); printf '"$missing%s$colorEnd %s$orphan%-${halfWidth}s$colorEnd/n"', $1, $2, $3}
 46     $2=="<" {
 47         # fill $3 with "-"
 48         $3="  ---------------------------------------------------------------------------"
 49         printf '"$orphan%s$colorEnd %s$missing%-${halfWidth}s$colorEnd/n"', $1, $2, substr($3, 0, '$halfWidth')
 50     }
 51     $2==" " {printf '"$common%s %s$common%-${halfWidth}s$colorEndn/n"', $1, $2, $3}
 52     $2!=" " && $2!="|" && $2!=">" && $2!="<" {printf '"$nondiff%s$colorEndn/n"', $0 }
 53     ')
 54 else
 55     diff "$@" --old-line-format="^[[1;31;47m<^[[1;31;40m %l^[[m
 56 " --new-line-format="^[[1;33;44m>^[[1;33;40m %l^[[m
 57 " --unchanged-line-format="^[[1;32m= %l^[[m
 58 "
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值