Shell命令-文件及内容处理之diff、vimdiff

文件及内容处理 - diff、vimdiff

1. diff:比较两个文件区别

diff命令的功能说明

diff命令用比较文件的差异。diff以逐行的方式,比较文本文件的异同处。如果指定要比较目录,则diff会比较目录中相同文件名的文件,但不会比较其中子目录。

diff命令的语法格式

diff [-abBcdefHilnNpPqrstTuvwy][-][-C ][-D ][-I ][-S ][-W ][-x ][-X ][--help][--left-column][--suppress-common-line][文件或目录1][文件或目录2]
diff [参数选项] [两个文件]

diff命令的选项说明

diff 选项很多,但是用的不多,表1为 diff 命令的参数及说明:

表1: diff命令的参数及说明

参数选项 解释说明
-  指定要显示多少行的文本。此参数必须与-c或-u参数一并使用。
-a或--text  diff预设只会逐行比较文本文件。
-b或--ignore-space-change  不检查空格字符的不同。
-B或--ignore-blank-lines  不检查空白行。
-c  显示全部内文,并标出不同之处。
-C或--context  与执行"-c-"指令相同。
-d或--minimal  使用不同的演算法,以较小的单位来做比较。
-D或ifdef  此参数的输出格式可用于前置处理器巨集。
-e或--ed  此参数的输出格式可用于ed的script文件。
-f或-forward-ed  输出的格式类似ed的script文件,但按照原来文件的顺序来显示不同处。
-H或--speed-large-files  比较大文件时,可加快速度。
-l或--ignore-matching-lines  若两个文件在某几行有所不同,而这几行同时都包含了选项中指定的字符或字符串,则不显示这两个文件的差异。
-i或--ignore-case  不检查大小写的不同。
-l或--paginate  将结果交由pr程序来分页。
-n或--rcs  将比较结果以RCS的格式来显示。
-N或--new-file  在比较目录时,若文件A仅出现在某个目录中,预设会显示:
Only in目录 文件A若使用-N参数,则diff会将文件A与一个空白的文件比较。
-p   若比较的文件为C语言的程序码文件时,显示差异所在的函数名称。
-P或--unidirectional-new-file  与-N类似,但只有当第二个目录包含了一个第一个目录所没有的文件时,才会将这个文件与空白的文件做比较。
-q或--brief  仅显示有无差异,不显示详细的信息。
-r或--recursive   比较子目录中的文件。
-s或--report-identical-files  若没有发现任何差异,仍然显示信息。
-S或--starting-file   在比较目录时,从指定的文件开始比较。
-t或--expand-tabs  在输出时,将tab字符展开。
-T或--initial-tab  在每行前面加上tab字符以便对齐。
-u,-U或--unified=  以合并的方式来显示文件内容的不同。
-v或--version  显示版本信息。
-w或--ignore-all-space  忽略全部的空格字符。
-W或--width  在使用-y参数时,指定栏宽。
-x或--exclude   不比较选项中所指定的文件或目录。
-X或--exclude-from  您可以将文件或目录类型存成文本文件,然后在=中指定此文本文件。
-y或--side-by-side   以并列的方式显示文件的异同之处。
--help  显示帮助。
--left-column   在使用-y参数时,若两个文件某一行内容相同,则仅在左侧的栏位显示该行内容。
--suppress-common-lines  在使用-y参数时,仅显示不同之处。

diff命令的实践操作

范例1: 备份 /etc/passwd,然后修改源文件,然后通过 diff 命令进行比较

--------------------------------------------------------------
==>备份/etc/passwd<==
--------------------------------------------------------------
[root@oldboyedu  ~]# cp /etc/passwd{,.ori}

--------------------------------------------------------------
==>源文件/etc/passwd添加内容<==
---------------------------------------------------------------
[root@oldboyedu  ~]# echo 'test' >> /etc/passwd

--------------------------------------------------------------
==>查看/etc/passwd添加的内容<==
--------------------------------------------------------------
[root@oldboyedu  ~]# tail -1 /etc/passwd
test

--------------------------------------------------------------
==>比较不同(也可以将两个文件分开写,要有空格)<==
--------------------------------------------------------------
[root@oldboyedu  ~]# diff /etc/passwd{,.ori}
25d24
< test

--------------------------------------------------------------
==>25行有新加的test<==
--------------------------------------------------------------
[root@oldboyedu  ~]# grep -n  -B3 'test' /etc/passwd
22-tcpdump:x:72:72::/:/sbin/nologin
23-nginx:x:1001:1001::/home/nginx:/sbin/nologin
24-ntp:x:38:38::/etc/ntp:/sbin/nologin
25:test

--------------------------------------------------------------
==>24行后,无内容,(过滤的内容实际而定)<==
--------------------------------------------------------------
[root@oldboyedu  ~]# grep -n  -A10 'tcpdump' /etc/passwd.ori
22:tcpdump:x:72:72::/:/sbin/nologin
23-nginx:x:1001:1001::/home/nginx:/sbin/nologin
24-ntp:x:38:38::/etc/ntp:/sbin/nologin

范例2: 并排格式输出

--------------------------------------------------------------
==>创建演示文本<==
--------------------------------------------------------------
[root@web01 /test]# seq -w 10 >oldboy.txt
[root@web01 /test]# cat oldboy.txt
01
02
03
04
05
06
07
08
09
10

--------------------------------------------------------------
==>备份源文件<==
--------------------------------------------------------------
[root@web01 /test]# cp oldboy.txt{,.ori}
[root@web01 /test]# cat oldboy.txt.ori
01
02
03
04
05
06
07
08
09
10

--------------------------------------------------------------
==>往源文件追加内容<==
--------------------------------------------------------------
[root@web01 /test]# echo 521 >> oldboy.txt

--------------------------------------------------------------
==>并排格式输出<==
--------------------------------------------------------------
[root@web01 /test]# diff oldboy.txt{,.ori} -y -W 50
01          01
02          02
03          03
04          04
05          05
06          06
07          07
08          08
09          09
10          10
521           <

说明:

  • | 表示前后2个文件内容有不同
  • < 表示后面文件比前面文件少了1行内容
  • > 表示后面文件比前面文件多了1行内容

2. vimdiff:快速比较和合并少量文件

vimdiff命令的功能说明

纯文本文件比较和合并工具一直是软件开发过程中比较重要的组成部分,vimdiff 能够在比较出来的多处差异之间快速定位,很容易的进行文件合并操作。在需要快速比较和合并少量文件的时候,vimdiff 是很好的选择。首先保证系统中的 diff 命令是可用的。Vimdiff 模式是依赖于 diff 命令的。

vimdiff命令的语法格式

vimdiff [options] file1 file2 [file3 [file4]]
vimdiff [参数选项] [两个文件]

vimdiff命令的选项说明

vimdiff 用的不多,这里就省略了

vimdiff命令的实践操作

范例1: 备份 /etc/passwd,然后修改源文件,然后通过 vimdiff 命令进行比较

使用vimdiff效果如下图所示:(vimdiff /etc/passwd /etc/passwd.ori)

Shell命令-文件及内容处理之diff、vimdiff

从上图我们可以看到一个清晰的比较结果。屏幕被垂直分割,左右两侧分别显示被比较的两个文件。两个文件中连续的相同的行被折叠了起来,以便使用者能把注意力集中在两个文件的差异上。只在某一文件中存在的行的背景色被设置为蓝色,而在另一文件中的对应位置被显示为绿色。两个文件中都存在,但是包含差异的行显示为粉色背景,引起差异的文字用红色背景加以突出。

如果希望交换两个窗口的位置,或者希望改变窗口的分割方式,可以使用下列命令:

  1. Ctrl-w K(把当前窗口移到最上边)
  2. Ctrl-w H(把当前窗口移到最左边)
  3. Ctrl-w J(把当前窗口移到最下边)
  4. Ctrl-w L(把当前窗口移到最右边)其中1和3两个操作会把窗口改成水平分割方式。

光标移动

接下来试试在行间移动光标,可以看到左右两侧的屏幕滚动是同步的。这是因为 scrollbind 选项被设置了的结果,vimdiff 会尽力保证两侧文件的对齐。如果不想要这个特性,可以设置:

:set noscrollbind

可以使用快捷键在各个差异点之间快速移动。跳转到下一个差异点:

]c

反向跳转是:

[c

如果在命令前加上数字的话,可以跳过一个或数个差异点,从而实现跳的更远。比如如果在位于第一个差异点的行输入 2]c,将越过下一个差异点,跳转到第三个差异点。

文件合并

文件比较的最终目的之一就是合并,以消除差异。如果希望把一个差异点中当前文件的内容复制到另一个文件里,可以使用命令

dp (diff "put")

如果希望把另一个文件的内容复制到当前行中,可以使用命令

do (diff "get",之所以不用dg,是因为dg已经被另一个命令占用了)

如果希望手工修改某一行,可以使用通常的 vimdiff 操作。如果希望在两个文件之间来回跳转,可以用下列命令序列:

Ctrl-w, w

在修改一个或两个文件之后,vimdiff 会试图自动来重新比较文件,来实时反映比较结果。但是也会有处理失败的情况,这个时候需要手工来刷新比较结果:

:diffupdate

如果希望撤销修改,可以和平常用 vim 编辑一样,直接

<ESC>, u

同时操作两个文件

在比较和合并告一段落之后,可以用下列命令对两个文件同时进行操作。比如同时退出:

:qa (quit all)

如果希望保存全部文件:

:wa (write all)

或者是两者的合并命令,保存全部文件,然后退出:

:wqa (write, then quit all)

如果在退出的时候不希望保存任何操作的结果:

:qa! (force to quit all)

上下文的展开和查看

比较和合并文件的时候经常需要结合上下文来确定最终要采取的操作。Vimdiff 缺省是会把不同之处上下各 6 行的文本都显示出来以供参考。其他的相同的文本行被自动折叠。如果希望修改缺省的上下文行数,可以这样设置:

:set diffopt=context:3

可以用简单的折叠命令来临时展开被折叠的相同的文本行:

zo (folding open,之所以用z这个字母,是因为它看上去比较像折叠着的纸)

然后可以用下列命令来重新折叠:

zc (folding close)

下图是设置上下文为 3 行,并展开了部分相同文本的 vimdiff 屏幕:

Shell命令-文件及内容处理之diff、vimdiff

结论

在无法使用图形化的比较工具的时候,或者在需要快速比较和合并少量文件的时候,vimdiff 是最好的选择。

今天就写到这里,有什么疑问或出现什么错误,随时欢迎大神们发表评论指点迷津

上一篇:Shell命令-文件及内容处理之cat、tac


下一篇:hihocoder 1037 数字三角形