• diff & pattch 命令


    • 基础知识

      该命令的功能为逐行比较两个文本文件,列出其不同之处。它比comm命令完成更复杂的检查。它对给出的文件进行系统的检查,并显示出两个文件中所有不同的行,不要求事先对文件进行排序。

      语法:diff [选项] file1 file2

      说明:该命令告诉用户,为了使两个文件file1和file2一致,需要修改它们的哪些行。如果用“- ”表示file1或fiie2,则表示标准输入。如果file1或file2是目录,那么diff将使用该目录中的同名文件进行比较。

      例如: diff /usr/xu mine

      把目录/usr/xu 中名为mine的文件与当前目录中的mine文件进行比较。

      通常输出由下述形式的行组成:

      n1 a n3,n4

         n1,n2 d n3

      n1,n2 c n3,n4 这些行类似ed命令把filel转换成file2。字母(a、d和c)之前的行号(n1,n2)是针对file1的,其后面的行号(n3,n4)是针对file2的。字母a、d和c分别表示附加、删除和修改操作。

      在上述形式的每一行的后面跟随受到影响的若干行,以“<”打头的行属于第一个文件,以“>”打头的行属于第二个文件

      diff能区别块和字符设备文件以及FIFO(管道文件),不会把它们与普通文件进行比较。

      如果file1和file2都是目录,则diff会产生很多信息。

      如果一个目录中只有一个文件,则产生一条信息,指出该目录路径名和其中的文件名。

      Diff 的common 选项的含义如下:

      - b 忽略行尾的空格,而字符串中的一个或多个空格符都视为相等。

      如How are you与How are you被视为相同的字符串。

      - c 采用上下文输出格式(提供三行上下文)。

      - C n 采用上下文输出格式(提供n行上下文)。

      - e 产生一个合法的ed脚本作为输出。

      - r 当file1和file2是目录时,递归作用到各文件和目录上。 

    • 实例分析

    diff的输出格式分为传统格式和统一格式

    1)diff的传统格式输出.

    ############################################
    cat before.txt
    输出:
    This is a line to be deleted
    This is a line that will be changed
    This is a line that will be unchanged

    cat after.txt
    输出: 
    This is a line that has been changed
    This is a line that will be unchanged
    This is a line that has been added
    ############################################
    diff before.txt after.txt 
    输 出:
    1,2c1
    < This is a line to be deleted
    < This is a line that will be changed
    ---
    > This is a line that has been changed
    3a3
    > This is a line that has been added
    ############################################

    注释:
    传统格式的输出
    1,2c1是指替换第1个文件的第1,2行到第2个文件的第2行,这里的1,2是指第1个文件的第1,2行,c是替换的意思,最后的1是第2个文件的第1行
    <号是指第1个文件更改或删除的行
    ---号是分割两个文件
    >号是第2个文件中增加或删除的行
    3a3是指将第2个文件的第3行插入到第一个文件的第3行
    也就是说第1个文件的:
    < This is a line to be deleted
    < This is a line that will be changed
    被替换成第2个文件的:
    > This is a line that has been changed
    由于第1个文件的第3行和第2个文件的第2行一致,所以不做修改.
    由于第2个文件的第3行是第1个文件所不具有的,所以在第1个文件的最后一行增加:
    > This is a line that has been added



    2)patch命令的应用

    用diff的传统格式输出:
    #################################
    diff before.txt after.txt >mypatch.txt
    #################################

    用patch修补before.txt文件,使before.txt和after.txt一致.
    #################################
    cat mypatch.txt |patch before.txt 
    输出:
    patching file before.txt
    #################################

    比较两个文件,现在是一致的了.
    #################################
    cmp before.txt after.txt 
    #################################

    用patch命令恢复before.txt.
    #################################
    patch -R before.txt <mypatch.txt
    输出:
    patching file before.txt
    #################################

    注:-R标记告诉patch在反向上应用区别或者撤销patch.

    再比较两个文件,现在不一致了.
    #################################
    cmp before.txt after.txt 
    输出:
    before.txt after.txt differ: byte 17, line 1
    #################################



    3)diff的统一格式输出.

    #################################
    diff -u before.txt after.txt |tee mypatch.diff
    输出:
    --- before.txt  2009-06-20 05:21:49.000000000 +0800
    +++ after.txt   2009-06-20 04:03:16.000000000 +0800
    @@ -1,3 +1,3 @@
    -This is a line to be deleted
    -This is a line that will be changed
    +This is a line that has been changed
     This is a line that will be unchanged
    +This is a line that has been added
    #################################

    注释:
    diff -u选项是统一格式输出.
    --- before.txt  2009-06-20 05:21:49.000000000 +0800
    --- before.txt是指旧文件
    +++ after.txt   2009-06-20 04:03:16.000000000 +0800
    +++ after.txt是指新文件.
    @@ -1,3 +1,3 @@
    @@ -1,3是指第1个文件一共有3行,+1,3 @@是指第2个文件一共有3行.
    -This is a line to be deleted
    -This is a line that will be changed
    是被删除的行
    +This is a line that has been changed
    是增加的行
     This is a line that will be unchanged
    没有-号和+号是指该行不变,因为after.txt和before.txt都有这行.
    +This is a line that has been added
    是增加的行
    diff的统一格式比较与输出是按顺序进行的.



    4)diff命令在目录中的应用.

    新建old和new目录,old目录包含了初始内容,new目录包含文件的最新版本.
    ##########################################
    mkdir old new
    echo "This is one. It's unchanged." | tee old/one new/one
    echo "This is two. It will change." > old/two
    echo "This is two. It changed.">new/two
    echo "This is three. It's new" > new/three
    ##########################################

    创建修补文件
    ##########################################
    diff -Nur old/ new/ >mypatch.diff
    ##########################################
    注:-r选项按照文件目录递归创建修补文件.
    -u还是统一模式
    -N是指当diff遇到一个只存在于两个树中的一个树中的文件时,默认情况下跳过文件并且打印一个警告到stderr.
    这个行为可以通过-N选项来更改,这也导致了diff认为丢失的文件实际上是存在的,但它是空的.采用这种方式,
    一个修补文件可以包括已经创建的文件.然后应用修补程序创建新的文件.

    ##########################################
    more mypatch.diff 
    输出:
    diff -Nur old/three new/three
    --- old/three   1970-01-01 08:00:00.000000000 +0800
    +++ new/three   2009-06-20 06:55:34.000000000 +0800
    @@ -0,0 +1 @@
    +This is three. It's new
    diff -Nur old/two new/two
    --- old/two     2009-06-20 06:55:08.000000000 +0800
    +++ new/two     2009-06-20 06:55:21.000000000 +0800
    @@ -1 +1 @@
    -This is two. It will change.
    +This is two. It changed.
    ##########################################
    注释:
    diff -Nur old/three new/three是指下面比较old/three new/three两个文件.
    因为没有old/three文件,所以在old/three中增加+This is three. It's new
    diff -Nur old/two new/two是指下面比较old/two new/two两个文件
    因为old/two与new/two的第3行不一致,所以删除This is two. It will change.增加This is two. It changed.


    打补丁到old目录,新建old/three以及更改old/two
    ##########################################
    patch --dir old< mypatch.diff
    ls -l     old/
    输出:
    one    three  two 
    ##########################################

    恢复old目录的内容,包括删除old/three,以及恢复old/two文件
    ##########################################
    patch --dir old -R <mypatch.diff
    输出:
    ls -l old/
    one  two  
    ##########################################



    5)检查和合并更改

    用vim突出显示单个字符的更改来表示区别.

    ##########################################
    vim -d after.txt before.txt
    ##########################################


    用gui工具gvimdiff来显示两个文件.

    ##########################################
    gvimdiff after.txt before.txt
    ##########################################


    新建文件orig.c

    ##########################################
    vi orig.c 
    void foo(void)
    {
        printf("This will be changed by me. /n");

        printf("This will be unchanged,/n");

        printf("This will be changed by you./n");
    }
    ##########################################


    复制文件orig.c到me.c,更改第4行为printf("This was changed by me. /n");
    ##########################################
    vi me.c 
    void foo(void)
    {
        printf("This was changed by me. /n");

        printf("This will be unchanged,/n");

        printf("This will be changed by you./n");
    }
    ##########################################


    复制文件orig.c到you.c,更改第7行为printf("This was changed by you./n");
    ##########################################
    vi you.c 
    void foo(void)
    {
        printf("This will be changed by me. /n");

        printf("This will be unchanged,/n");

        printf("This was changed by you./n");
    }
    ##########################################

    版本工具如cvs,subversion使用GNU合并工具称为diff3.
    ##########################################
    diff3 me.c orig.c you.c 
    输出:
    ====1
    1:3c
          printf("This was changed by me. /n");
    2:3c
    3:3c
          printf("This will be changed by me. /n");
    ====3
    1:7c
    2:7c
          printf("This will be changed by you./n");
    3:7c
          printf("This was changed by you./n");

    注:
    在没有参数的情况下,diff3产生的输出说明了那行更改.
    ====1和====3指明造成同原始文件不同的是哪一个修改文件.
    编号方式基于参数序列.
    也就是第1个文件和第3个文件与原文件不同.
    1:3c
          printf("This was changed by me. /n");
    3:3c
          printf("This will be changed by me. /n");
    1:3c表示第1个文件的第3行与3:3c表示的第3个文件的第3行不同.
    为什么不显示与原文件的比较呢。因为第3个文件的第3行与源文件(第2个文件)相同.所以与哪个文件比较无所谓了.

    2:7c
          printf("This will be changed by you./n");
    3:7c
          printf("This was changed by you./n");
    2:7c表示第2个文件的第7行与3:7c表示的第3个文件的第7行不同.


    diff3会试图为我们进行合并.合并是在源文件的基础上,依据两个新文件进行修改
    源文件是第二个文件,第一个文件和第三个文件可以互换,但他们必须有共同的祖先,就是第二个文件.

    #######################################
    diff3 -m me.c orig.c you.c |cat -n
    输出:
         1    void foo(void)
         2    {
         3        printf("This was changed by me. /n");
         4    
         5        printf("This will be unchanged,/n");
         6    
         7        printf("This was changed by you./n");
         8    }
    ########################################


    为了测试更复杂的环境,新建一个文件orig.c.1
    内容如下:
    ########################################
    vi orig.c.1 
    void foo(void)
    {
        printf("This will be changed by both of us./n");
    }
    ########################################


    用diff3 -m再次比较输出,如下:
    ########################################
    diff3 -m me.c orig.c.1 you.c 
    void foo(void)
    {
    <<<<<<< me.c
        printf("This was changed by me. /n");

        printf("This will be unchanged,/n");

        printf("This will be changed by you./n");
    ||||||| orig.c.1
        printf("This will be changed by both of us./n");
    =======
        printf("This will be changed by me. /n");

        printf("This will be unchanged,/n");

        printf("This was changed by you./n");
    >>>>>>> you.c
    }
    ########################################

    注释:以上的格式,同cvs update,需要人工合并文件的格式是一致的.

  • 相关阅读:
    emacs 集成astyle
    git reflog
    rpm 打包的时候 不进行strip
    gmock
    如何对正在运行的进程,进行heap profile
    linux性能压测工具
    默认宏定义
    gdb fabs错误输出
    基于Clang的缓存型C++编译器Zapcc
    grep 多行 正则匹配
  • 原文地址:https://www.cnblogs.com/zhaoyl/p/3799291.html
Copyright © 2020-2023  润新知