差异两个文件与切换行的结果说两次丢失同一行


28

我试图理解两个文件的linux diff命令,它们的行只是彼此置换,但无法查看其生成的输出。请考虑以下三个命令:

[myPrompt]$ cat file1
apples
oranges
[myPrompt]$ cat file2 
oranges
apples
[myPrompt]$ diff file1 file2
1d0
< apples
2a2
> apples

有人可以解释diff的上述神秘输出。

  1. 为什么输出中根本没有提到“橙色”?
  2. 是什么1d02a2意味着什么?

从这个答案中了解到:

“ <”表示文件2中缺少该行,而“>”表示文件1中缺少该行

但是并不能解释为什么输出中缺少橙子。


12
因为oranges是两个文件之间最大的共同部分,所以您获得的是表达两者之间差异的最短方法。
斯特凡Chazelas

10
而且,如果您想获得更具可读性的输出,请diff -u file1 file2改用。这就是所谓的“统一差异”格式。原始的diff格式本来应该非常紧凑,但是统一的diff则要可读得多。
godlygeek

4
@godlygeek或diff -y file1 file2
user80551

Answers:


27

要理解该报告,请记住这diff是说明性的,描述了对第一个文件(file1)进行哪些更改才能使其与第二个文件(file2)相同。

具体来说,din 1d0表示删除ain 2a2表示添加

从而:

  • 1d0表示必须在file1apples)中删除第1行。0in 1d0表示如果file2未删除它们,它们将在第二个文件()中出现在第0行。这意味着当更改file2file1(向后)时,file1在的第0 行之后追加第1 行file2
  • 2a2表示将第二行(oranges)附加file2到的第二行file1(删除的第一行之后file1oranges切换到第一行)

是什么01d0
极客2014年

@Geek看我的编辑
混乱

1
@Geek但是要小心,那会在大脑中打结=)
混乱

确实开始打结了:-)
极客2014年

13

考虑以下文件:

file1

# cat file1
apples
pears
oranges
peaches

file2

# cat file2
oranges
apples
peaches
ananas
banana

diff鉴于它是基于订单的,如何工作:

  1. diff读取的线的第一个块file1file2,并试图找到等于行:

      file1        file2        differences on left (<) or right side (>)
      apples                   <apples
      pears                    <pears 
      -------------------------------
    ->oranges    ->oranges
      peaches      apples
                   peaches
                   ananas
                   banana
    
  2. 现在,它将跳过两个文件中所有相等的行,oranges在这种情况下:

      file1        file2        differences on left (<) or right side (>)
      apples                   <apples
      pears                    <pears 
      oranges      oranges
      -------------------------------
    ->peaches    ->apples
                   peaches
                   ananas
                   banana
    
  3. 现在找到另一组相似的行并打印出差异:

      file1        file2        differences on left (<) or right side (>)
      apples                   <apples
      pears                    <pears 
      oranges      oranges
                   apples      >apples
      -------------------------------
    ->peaches    ->peaches
                   ananas
                   banana
    
  4. 跳过类似的行

      file1        file2        differences on left (<) or right side (>)
      apples                   <apples
      pears                    <pears 
      oranges      oranges
                   apples      >apples
      peaches      peaches
      -------------------------------
    ->           ->ananas
                   banana
    
  5. 如果可能,找到相同的行并打印差异:

    line_file1    file1    line_file2    file2        differences on left (<) or right side (>)
             1    apples                              <apples 
             2    pears                               <pears 
             3    oranges           1    oranges
                                    2    apples       >apples
             4    peaches           3    peaches
                                    4    ananas       >ananas
                                    5    banana       >banana
             -----------------------------------------------
    

现在,如果我这样做diff file1 file2

# diff file1 file2
1,2d0
< apples
< pears
3a2
> apples
4a4,5
> ananas
> banana

现在很容易解释什么 diff输出的含义:

使file1等于file2

  • 1,2d0删除d)线1-2file1和修改线0file2相应
  • 3a2a附加到行3file12file2
  • 4a4,5追加到线4file1线4-5file2

diff比较file1file2由在临时存储器线并稳定差异线。在file1 等于 file2直到第一次出现in的行(file1也出现在)之后file2,没有提及直到差值才相等的所有行,通常表示为---。在这种情况下,只有一条相似的线是oranges。请注意,我说的file1file2,所以file1是相对于file2而不是相反的。

在这种情况下,输出与给定的第一个文件有关file1


2
我不喜欢最初的解释:apples两个文件中也都出现了。
OR Mapper 2014年

1
@ORMapper我更改了解释。现在听起来更清晰/更好吗:)?
polym 2014年

不完全是,目前您写的是“只有一条相似的线,那就是oranges”。错误:实际上有两条线,不仅相似,而且绝对相同。其中一个读oranges,另一个读apples。此外,您的解释(完全基于顺序)与斯特凡(Stéphane)对问题的评论(基于长度)相矛盾-谁是正确的?
OR Mapper 2014年

@ORMapper您忘记了“在这种情况下”以及之前的代码。我的意思是,在这一步中只有一条相似的线。我将在示例中添加一个示例,以便更好地理解它。
polym 2014年

1
@ORMapper还可以举一个例子说明基于长度的答案是正确的吗?
polym 2014年

8

它们是:

$ diff file1 file2
1d0
< apples
2a2
> apples
$ diff file2 file1
1d0
< oranges
2a2
> oranges

8

标准(旧)输出格式将显示文件之间的差异,而不会在文件周围带有区域差异的文本周围显示。

例如:(1d0 <删除)表示需要从的第一行中删除苹果file1,而2a2 >(追加)表示需要将苹果添加到file2在第二行中,因此两个文件都可以匹配。

可用的文档info diff进一步解释了它:

在没有上下文的情况下显示差异

“正常” diff输出格式显示了每个差异,没有任何周围的上下文。有时,这样的输出是查看行的变化的最清晰方法,而不会造成附近不变的行的混乱(尽管您可以通过使用0行上下文获得与上下文相似的结果或统一格式)。但是,这种格式已不再广泛用于发送补丁。为此,上下文格式和统一格式是更好的。缺省格式是标准格式,以与diffPOSIX标准的较早版本兼容。使用该--normal选项可以显式选择此输出格式。

普通格式的详细说明

普通输出格式由一个或多个大块差异组成;每个块显示一个文件不同的区域。普通格式的块看起来像这样:

 CHANGE-COMMAND
 < FROM-FILE-LINE
 < FROM-FILE-LINE...
 ---
 > TO-FILE-LINE
 > TO-FILE-LINE...

更改命令有三种类型。每个文件都由第一个文件中的行号或以逗号分隔的范围,单个字符(指示要进行的更改的种类)以及第二个文件中的行号或以逗号分隔的范围组成。所有行号都是每个文件中的原始行号。更改命令的类型为:

LaR 在第一个文件的第L行之后,在第二个文件的范围R中添加行。例如,8a12,15意味着在文件1的第8行之后追加文件2的第12-15行;或者,如果将文件2更改为文件1,则删除文件2的第12-15行。

FcT 用第二个文件的范围T中的行替换第一个文件的范围F中的行。这就像组合的添加和删除,但更为紧凑。例如,5,7c8,10意味着将文件1的第5-7行更改为文件2的第8-10行;或者,如果将文件2更改为文件1,则将文件2的第8-10行更改为文件1的第5-7行。

RdL 从第一个文件中删除范围R中的行;如果没有删除它们,L行将显示在第二个文件中。例如,5,7d3表示删除文件1的第5-7行;或者,如果将文件2更改为文件1,则在文件2的第3行之后附加文件1的第5-7行。

也可以看看:


因此,要查看橙子,您必须并排或使用统一上下文对其进行比较。

例如:

$ diff -y file1 file2
apples                                <
oranges                             oranges
                                  > apples

$ diff -u file1 file2
@@ -1,2 +1,2 @@
-apples
 oranges
+apples
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.