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参数
这种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的内容
现在就把整个的代码都贴出来,这个脚本名为cdiff,就是colorful diff的意思
可以支出如下的几种用法
cdiff file1 file2, cat file1 |cdiff - file2 , 效果如图一
cdiff -y file1 file2 ,diff -y file1 file2 |cdiff,效果如图二
cvs diff file |cdiff,效果如下
代码在这里
一般情况下,diff的输出是不便阅读的,例如
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
那么如何让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 `-'.
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 `-'.
掌握了diff的简单参数对于使用cvs命令行的人是个福音,因为在cvs diff的时候,也是可以制定这些参数的,这样在看两个版本的代码的时候就很方便了
diff的高级功能
diff在如何显示结果的问题上面,为用户提供了很大的定制空间。下面我们就让diff的输出有颜色,至少可以达到windiff的效果
对于如何在终端上面显示颜色的问题,可以参考我的 另外一篇博客
diff提供了几个选项
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
下面我们就如此定制一下diff的输出
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
这样的输出还是很漂亮的吧
而且这样指定输出格式的选项可以完全的使用在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的效果。
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
现在就把整个的代码都贴出来,这个脚本名为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 "
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 "