zoukankan      html  css  js  c++  java
  • 比较两个UNIX文本文件,找出新增内容(diff和comm命令)(转)

    本文转自 http://blog.xuyuan.me/2011/03/17/unix_diff.html

    最近项目中遇到一个奇怪的bug,仔细检查后发现是由一行简单代码引起的。这行代码要做的事情很简单:比较两个UNIX文本文件,找出并打印文本2比文本1新增加的内容。代码调用了diff命令,示例如下:

    # temp1.txt文件内容
    $> cat temp1.txt
    20110224
    20110225
    20110228
    20110301
    20110302

    # temp2.txt文件内容
    $> cat temp2.txt
    20110228
    20110301
    20110302

    20110303
    20110304

    # diff命令输出结果
    $> diff temp1.txt temp2.txt
    1,2d0
    < 20110224
    < 20110225
    5a4,5
    > 20110303
    > 20110304

    # 只输出temp2.txt文件独有的内容
    $> diff temp1.txt temp2.txt | grep "> " | sed 's/> //g'
    20110303
    20110304

    可以看到,输出结果去掉了两个文件的共同内容,只输出了temp2.txt的新增部分,和预想的结果一样。

     

    但是,随着temp1.txt文件内容的增加,diff命令出现了不同预期的结果:

    $> cat temp1.txt
    20101216
    20101217
    20101220
    20101221
    20101223
    20101224
    20101227
    20101228
    20101229
    20101230
    20101231
    20110103
    20110104
    20110105
    20110106
    20110107
    20110110
    20110111
    20110112
    20110113
    20110114
    20110117
    20110118
    20110119
    20110120
    20110121
    20110124
    20110125
    20110126
    20110127
    20110128
    20110131
    20110201
    20110202
    20110203
    20110204
    20110207
    20110208
    20110209
    20110210
    20110211
    20110214
    20110215
    20110216
    20110217
    20110218
    20110221
    20110222
    20110223
    20110224
    20110225
    20110228
    20110301
    20110302
    20110303

    $> cat temp2.txt
    20110228
    20110301
    20110302
    20110303

    20110304
    20110307
    20110308
    20110309
    20110310
    20110311
    20110314

    $> diff temp1.txt temp2.txt
    1,55c1,11
    < 20101216
    < 20101217
    < 20101220
    < 20101221
    < 20101223
    < 20101224
    < 20101227
    < 20101228
    < 20101229
    < 20101230
    < 20101231
    < 20110103
    < 20110104
    < 20110105
    < 20110106
    < 20110107
    < 20110110
    < 20110111
    < 20110112
    < 20110113
    < 20110114
    < 20110117
    < 20110118
    < 20110119
    < 20110120
    < 20110121
    < 20110124
    < 20110125
    < 20110126
    < 20110127
    < 20110128
    < 20110131
    < 20110201
    < 20110202
    < 20110203
    < 20110204
    < 20110207
    < 20110208
    < 20110209
    < 20110210
    < 20110211
    < 20110214
    < 20110215
    < 20110216
    < 20110217
    < 20110218
    < 20110221
    < 20110222
    < 20110223
    < 20110224
    < 20110225
    < 20110228
    < 20110301
    < 20110302
    < 20110303

    ---
    > 20110228
    > 20110301
    > 20110302
    > 20110303

    > 20110304
    > 20110307
    > 20110308
    > 20110309
    > 20110310
    > 20110311
    > 20110314

    $> diff temp1.txt temp2.txt | grep "> " | sed 's/> //g'
    20110228
    20110301
    20110302
    20110303

    20110304
    20110307
    20110308
    20110309
    20110310
    20110311
    20110314

    可以看到,diff命令不但输出了temp2.txt文件的新增部分(20110304-20110314),也同时输出了两个文件的共同内容(20110228-20110303),从而导致了与预期不一致的结果。

    查看diff命令的man手册发现,diff的作用是比较两个文件的内容,并输出两个文件之间的差异,产生一个能够将两个文件互相转换的列表,但这个列表并不能100%保证是最小集。于是,在上面的例子中,我们看到diff给出了temp1.txt和temp2.txt文件的比较差异结果,但其中包含了两个文件的共同部分,因此与预期不一样。

     

    一个解决的方法是,可以用comm命令代替diff,示例如下:

    $> comm -13 temp1.txt temp2.txt
    20110304
    20110307
    20110308
    20110309
    20110310
    20110311
    20110314

    comm命令用来比较两个文件,具体用法:

    comm [-123] file1 file2
    -1 过滤file1独有的内容
    -2 过滤file2独有的内容
    -3 过滤file1和file2重复的内容

     

    PS,看了下diff的输出格式,主要有以下几种:

    n1 a n3,n4
    n1,n2 d n3
    n1,n2 c n3,n4

    例如"1,2d0" "5a4,5" "1,55c1,11"等。其中n1和n2指第一个文件的行数,n3和n4指第二个文件的行数。"a"代表add增加,"d"代表delete删除,"c"代表change整块变动。

    有了diff的输出结果,可以使用patch命令将一个文件恢复成另一个,例如:

    $> cat temp1.txt
    20110224
    20110225
    20110228
    20110301
    20110302

    $> cat temp2.txt
    20110228
    20110301
    20110302
    20110303
    20110304

    $> diff temp1.txt temp2.txt > temp.diff

    $> cat temp.diff
    1,2d0
    < 20110224
    < 20110225
    5a4,5
    > 20110303
    > 20110304

    # 使用temp.diff和temp1.txt恢复temp2文件
    $> patch -i temp.diff -o temp2_restore.txt temp1.txt
    Looks like a normal diff.
    done

    # 完成后temp2_restore和原temp2文件内容一致
    $> cat temp2_restore.txt
    20110228
    20110301
    20110302
    20110303
    20110304


    博主ma6174对本博客文章(除转载的)享有版权,未经许可不得用于商业用途。转载请注明出处http://www.cnblogs.com/ma6174/

    对文章有啥看法或建议,可以评论或发电子邮件到ma6174@163.com


  • 相关阅读:
    统计数据持久化
    缓存层的实现
    C++语法疑点
    为什么需要定义虚的析构函数?
    C++ shared_ptr deleter的实现
    条件变量
    ubuntu  输入时弹出剪切板候选项
    leetcode Bitwise AND of Numbers Range
    C/C++ 字符串 null terminal
    C++ inline weak symbol and so on
  • 原文地址:https://www.cnblogs.com/ma6174/p/2348904.html
Copyright © 2011-2022 走看看