分类: Linux

Linux下比较两个文件内容的异同

业务上需要根据MySQL的mysql-bin.index实现增量数据同步恢复,用到了文件对比,方法记录如下:
一:comm命令实现
comm命令的参数

-1 不显示只在第1个文件里出现过的列。
-2 不显示只在第2个文件里出现过的列。
-3 不显示只在第1和第2个文件里出现过的列。

常用的用法如下:
comm -12 就只显示在两个文件中都存在的行;
comm -23 只显示在第一个文件中出现而未在第二个文件中出现的行;
comm -3 显示第一个文件中未出现,在第二个中出现的内容
如 comm -3 2017060612_bin.log /home/data/mysql/binlog/mysql-bin.index
运行结果如下

    /home/data/mysql/binlog/mysql-bin.009021
    /home/data/mysql/binlog/mysql-bin.009022    

两个文件的内容在比较前,一定要进行sort排序。不然输出的结果将是错误的,就是说顺序必须一致

二:diff命令比较
diff命令是一个比较经典的文本比较工具了,diff命令较comm的参数要多。其经常和patch命令组合使用,进行补丁升级。其默认使用的是-a参数,即逐行比较两个文件之间的不同。此处我们要实现想要得到的结果,还需要配合grep和awk实用:

diff 2.txt 1.txt |grep "<"|awk ' $1 = " " '
注:此处也发现,在使用diff命令进行比较时,也需要预先对经比较的文件进行sort排序,不然输出的结果同样是不正确的。
FILES的格式:

FILE1 FILE2 :源是一个文件,目标也是文件。这两个文件必须是文本文件。以逐行的方式,比较文本文件的异同处。
DIR1 DIR2 :源是一个目录,目标是目录。diff 命令会比较两个目录下名字相同的文本文件,依照字母次序排序,列出不同的二进制文件,列出公共子目录,列出只在一个目录出现的文件。
FILE DIR :源是一个文件,目标是目录。diff命令把源文件与目标目录下的同名文件比较。
DIR FILE :源是一个目录,目标是文件(不是目录)。源目录下所有文件中与目标文件同名的文件,将用来与目标文件比较。
FILE可以是“-”,代表由标准输入设备读入的文本。DIR不能是"-"。
被指定的文件不能是标准的输入。

短选项 长选项 含义
-i --ignore-case 忽略文件内容大小写的区别

 --ignore-file-name-case    忽略文件名大小写的区别
 --no-ignore-file-name-case    不忽略文件名大小写的区别

-E --ignore-tab-expansion 忽略由制表符宽度造成的差异
-b --ignore-space-change 忽略由空格数不同造成的差异
-w --ignore-all-space 忽略所有空格
-B --ignore-blank-lines 忽略任何因空行而造成的差异
-I --ignore-matching-lines=RE 如果某行匹配正则表达式,则忽略由该行造成的差异
-a --text 所有文件都以文本方式处理

 --strip-trailing-cr    去除输入内容每行末端的 carriage return 字符

-c 或 或 -C 行数 --context[=行数] 显示指定<行数>(默认 3 行)copied 格式的上下文

-u 或 -U 行数 --unified[=行数] 显示指定<行数>(默认 3 行)unified 格式的上下文(合并的方式)

 --label 标识    使用<标识>代替文件名称

-p --show-c-function 显示和每个差异有关的 C 函数名称
-F --show-function-line=RE 显示最接近而符合<正则表示式>的一行
-q --brief 只显示文件是否不同
-e --ed 以 ed script 方式输出

 --normal    以正常的 diff 方式输出

-n --rcs 以 RCS diff 格式输出
-y --side-by-side 以两列并排的方式显示
-W --width=NUM 每行显示最多 NUM (默认 130) 个字符

 --left-column    当有两行相同时只显示左边的一行
 --suppress-common-lines    当有两行相同时不会显示

-D --ifdef=NAME 输出的内容以‘#ifdef NAME’方式标明差异

 --GTYPE-group-format=GFMT    效果类似,但会以 GFMT 格式处理 GTYPE 输入的行

可以是LTYPE的选择或是‘changed’

 --line-format=LFMT    效果类似,但会以 LFMT 格式处理每一行资料
 --LTYPE-line-format=LFMT    效果类似,但会以 LFMT 格式处理 LTYPE 输入的行

LTYPE 可以是‘old’、‘new’或‘unchanged’。
-l --paginate 将输出送至‘pr’指令来分页
-t --expand-tabs 将输出中的 tab 转换成空格
-T --initial-tab 每行先加上 tab 字符,使 tab 字符可以对齐

 --tabsize=NUM    定位字符 (tab) 的宽度,默认为 8 个空格宽
 --suppress-blank-empty    suppress space or tab before empty output lines

-r --recursive 递归比较子目录中的文件
-N --new-file 不存在的文件以空文件方式处理

 --unidirectional-new-file    若第一文件案不存在,以空文件处理

-s --report-identical-files 文件相同则报告,否则无任何提示
-x --exclude=PAT 排除匹配 PAT 的文件
-X --exclude-from=FILE 排除所有匹配在 FILE 中列出的模式的文件
-S --starting-file=FILE 当比较目录時,由 FILE 开始比较

 --from-file=FILE1    将 FILE1 和操作数中的所有文件/目录作比较。FILE1 可以是目录
 --to-file=FILE2    将操作数中的所有文件/目录和 FILE2 作比较。FILE2 可以是目录
 --horizon-lines=NUM    keep NUM lines of the common prefix and suffix

-d --minimal 尽可能找出最小的差异

 --speed-large-files    假设文件十分大而且其中含有许多微小的差异

diff输出格式(默认):
n1 a n3,n4 表示在文件1的n1行后面添加n3到n4行
n1,n2 d n3 表示在n1到n2行之间删除n3行
n1,n2 c n3,n4 表示把n1,n2行用n3,n4行替换掉
字母a:表示附加(add)
字符c:表示修改(change)
字符d:表示删除(delete)
字母前的是源文件,字母后是目标文件。Nx表示行号。
以”<”打头的行属于第一个文件,以”>”打头的行属于第二个文件。
更多diff参考:http://www.lampweb.org/linux/3/17.html

三:awk实现

awk应该算是shell常用命令中的泰山北斗了,几乎很多其他命令能完成的工作,awk都能完成(只不过有些写起来可能比较复杂)。本例中也不例外:

awk 'NR==FNR{a[$0]++} NR>FNR&&!a[$0]' 1.txt 2.txt
找出两个文件之间的相同部分可以使用

awk 'NR==FNR{a[$0]++} NR>FNR&&a[$0]' 1.txt 2.txt
下面的两个语句也可以换成:

awk 'NR==FNR{a[$0]}NR>FNR{ if(!($1 in a)) print $0}' file1 file2 找出文件2中不同的值
awk 'NR==FNR{a[$0]}NR>FNR{ if($1 in a) print $0}' file1 file2 找出两文件中相同的值
注:

1、awk实现时,并不需要事先对两个文件进行sort排序,
2、注意和上两个命令中两个文件的放置顺序是不同的。三种实现方法,文件的顺序一定颠倒,颠倒了,效果就刚好想反了,就变成找出文件1中有文件2中没有的行了。

四、grep排序
grep -v -f 1.txt 2.txt

如grep -v -f 2017060614_bin.log /home/data/mysql/binlog/mysql-bin.index
/home/data/mysql/binlog/mysql-bin.009021
/home/data/mysql/binlog/mysql-bin.009022

grep常用用法
grep [-acinv] [--color=auto] '搜寻字符串' filename
选项与参数:
-a :将 binary 文件以 text 文件的方式搜寻数据
-c :计算找到 '搜寻字符串' 的次数
-i :忽略大小写的不同,所以大小写视为相同
-n :顺便输出行号
-v :反向选择,亦即显示出没有 '搜寻字符串' 内容的那一行!
--color=auto :可以将找到的关键词部分加上颜色的显示喔!

相关文章

发表新评论