为什么使用忽略匹配行的diff不能按预期工作?

时间:2013-04-04 09:18:16

标签: shell diff ignore

我有以下文件:

FILE1.TXT

###################################################
Dump stat Title information for 'ssummary' view
###################################################
Tab=> 'Instance' Title=> {text {Total instances: 7831}}
Tab=> 'Device' Title=> {text {Total spice devices: 256}}
Tab=> 'Memory' Title=> {text {Total memory allocated: 962192 kB}}
Tab=> 'Cpu' Title=> {text {Total cumulative CPU time: 9030 ms}}

FILE2.TXT

###################################################
Dump stat Title information for 'ssummary' view
###################################################
Tab=> 'Instance' Title=> {text {Total instances: 7831}}
Tab=> 'Device' Title=> {text {Total spice devices: 256}}
Tab=> 'Memory' Title=> {text {Total memory allocated: 9621932 kB}}
Tab=> 'Cpu' Title=> {text {Total cumulative CPU time: 90303 ms}}

我正在运行以下命令:

diff -I 'Memory' file1.txt file2.txt

输出:

6,7c6,7
< Tab=> 'Memory' Title=> {text {Total memory allocated: 962192 kB}}
< Tab=> 'Cpu' Title=> {text {Total cumulative CPU time: 9030 ms}}
---
> Tab=> 'Memory' Title=> {text {Total memory allocated: 9621932 kB}}
> Tab=> 'Cpu' Title=> {text {Total cumulative CPU time: 90303 ms}}

但是我的预期输出是:

< Tab=> 'Cpu' Title=> {text {Total cumulative CPU time: 9030 ms}}
---
> Tab=> 'Cpu' Title=> {text {Total cumulative CPU time: 90303 ms}}

请注意,在命令中如果我将“Memory”更改为“Tab”或“Title”问题已解决,但可能所有行都被忽略,因为它们都有Tab和Title。

5 个答案:

答案 0 :(得分:4)

这种行为看起来确实有些奇怪。我通过调整输入文件注意到了一些事情(我只是将“Memory”行移到了两个文件的顶部):

FILE1.TXT

###################################################
Dump stat Title information for 'ssummary' view
###################################################
Tab=> 'Memory' Title=> {text {Total memory allocated: 962192 kB}}
Tab=> 'Instance' Title=> {text {Total instances: 7831}}
Tab=> 'Device' Title=> {text {Total spice devices: 256}}
Tab=> 'Cpu' Title=> {text {Total cumulative CPU time: 9030 ms}}

FILE2.TXT

###################################################
Dump stat Title information for 'ssummary' view
###################################################
Tab=> 'Memory' Title=> {text {Total memory allocated: 9621932 kB}}
Tab=> 'Instance' Title=> {text {Total instances: 7831}}
Tab=> 'Device' Title=> {text {Total spice devices: 256}}
Tab=> 'Cpu' Title=> {text {Total cumulative CPU time: 90303 ms}}

普通差异会给你:

diff file1.txt file2.txt

4c4
< Tab=> 'Memory' Title=> {text {Total memory allocated: 962192 kB}}
---
> Tab=> 'Memory' Title=> {text {Total memory allocated: 9621932 kB}}
7c7
< Tab=> 'Cpu' Title=> {text {Total cumulative CPU time: 9030 ms}}
---
> Tab=> 'Cpu' Title=> {text {Total cumulative CPU time: 90303 ms}}

请注意,现在有两组差异......使用这种安排,diff -I 'Memory' file1.txt file2.txt命令工作并输出:

7c7
< Tab=> 'Cpu' Title=> {text {Total cumulative CPU time: 9030 ms}}
---
> Tab=> 'Cpu' Title=> {text {Total cumulative CPU time: 90303 ms}}

意思是,只有当一组差异中的每一行都与表达式匹配时,-I标志才会起作用。我不知道这是一个错误还是预期的行为......但它肯定是不一致的。


编辑:实际上,根据GNU diff documentation,这是预期的行为。手册页不太清楚。 OpenBSD diff也有一个-I标志,但their man page更好地解释了它。

答案 1 :(得分:4)

考虑到diff的工作方式(截至2013年4月),此行为是正常的。

diff是面向行的,它意味着一条线被认为是完全不同的或完全等价的。忽略一行时,在比较之前将其输入到不同行的列表中,并且在计算更改脚本时,仅对忽略的行所做的更改将被视为已忽略。当忽略的行与更改的行相邻时,它会构成一个不可忽略的更改。

问题在于diff无法理解连续的行是不相关的:你没有区分一系列文本(diff的目的是什么),而是一个独立的列表键入的行(Tab >= <key>)。当两个文件以相同的顺序生成时,这些问题看起来非常相似,但仍然不一样。

答案 2 :(得分:2)

你每天都学到新东西。我对此行为同样感到困惑和沮丧,这似乎大致是[差异输入文件,然后过滤出RE],而不是[过滤RE输出文件,然后差异]。

我认为第二种方法更自然,更有用。例如,这似乎是--ignore-case和--strip-trailing-cr的工作方式,在diffing之前调整输入文件。此外,实际上实现提问者想要的内容涉及过滤临时文件的两个输入,对它们进行区分,然后删除它们。如果你想像我一样做一个递归差异,那就变得更加乏味了。

我承认diff的行为与它的记录方式不同,而不是我希望它的行为,但尊重地建议这个选项(和-b,-w类似)可以有用地添加到diff。

答案 3 :(得分:1)

这是符合diffutils手册的预期行为:

  

但是,-I只有忽略插入或删除包含正则表达式的行,如果每个更改的行中的(每次插入和每次删除) )匹配正则表达式

     

换句话说,对于每个不可忽略的更改,diff会在其附近打印完整的更改集,包括可忽略的更改。您可以使用多个-I选项为要忽略的行指定多个正则表达式。 diff尝试将每一行与每个正则表达式匹配,从给定的最后一个开始。 man diff)功能

您可以尝试通过指定-d来设置较小的更改集,但在您的示例中,它将无效。

  

-d --minimal尽量找到一小组更改。

答案 4 :(得分:0)

从人类差异来看,如果我记得很清楚的话,我只会忽略其中包含的reg exp。 这意味着如果f1是:

the pen is on the table

和f2是:

the pun is on the table

会正确解析:

diff -I 'p.n' f2 f2
什么都没有

BUT

如果f2现在变为

the pun is on the cable

正则表达式不再匹配(电缆和表格与正则表达式不匹配......)所以你会在输出中出现两条线...

因此,只需尝试更改命令:

diff -I '.*Memory.*' file1.txt file2.txt

应该做的伎俩(抱歉愚蠢的例子......)