【问题标题】:vimdiff: force line-by-line comparison (ignore supposedly missing/additional lines)vimdiff:强制逐行比较(忽略所谓的缺失/附加行)
【发布时间】:2015-01-05 14:07:54
【问题描述】:

如何强制 vimdiff 始终逐行比较两个文件而不识别添加或删除的行?

问题是,如果两个文件之间的差异很大,但是文件中的两行偶然匹配,vimdiff 认为这些行是相同的,只是将其余的视为添加或删除的行,结果差异是完全无法使用。就我而言,file1 中的第 i 行始终对应于 file2 中的第 i 行,因此 vimdiff 没有业务查找添加或删除的行。

以下是一个小示例,其中包含两个文件,每个文件包含三个变量的值。 Vimdiff 错误地将 file1/line1 与 file2/line3 匹配,并认为它周围的一些行已被添加或删除。差异(减去颜色)看起来像这样:

              |  1 foo 8.1047  < del/new
              |  2 bar 6.2343  < del/new
1 foo 0.0000  |  3 foo 0.0000  < match
2 bar 5.3124  |  4 bar 1.4452  < wrong
3 foo 4.5621  |                < new/del
4 bar 6.3914  |                < new/del
5 foo 1.0000  |  5 foo 1.0000  < match
6 bar 6.3212  |  6 bar 7.2321  < wrong

然而,我想要的是以下内容,除了匹配的第 5 行之外,所有行都标记为错误:

1 foo 0.0000  |  1 foo 8.1047 < wrong
2 bar 5.3124  |  2 bar 6.2343 < wrong
3 foo 4.5621  |  3 foo 0.0000 < wrong
4 bar 6.3914  |  4 bar 1.4452 < wrong
5 foo 1.0000  |  5 foo 1.0000 < match
6 bar 6.3212  |  6 bar 7.2321 < wrong

【问题讨论】:

  • 你可能想使用 "sdiff file1 file2" 而不是 vimdiff ?
  • @OlivierDulac:不,不是真的,我在这些情况下比较的文件要长得多,我想滚动浏览它们,所以 vimdiff 很好。不过,我不知道sdiff,它绝对可以方便地比较短文件。

标签: vim diff vimdiff


【解决方案1】:

当我复制这个例子来尝试它时,我注意到vimdiff 会做你想做的事,如果你有与每一行相关的行号。

因此,您可以使用cat添加行号,然后进行差异:

  cat -n file1 > file1_with_line_no
  cat -n file2 > file2_with_line_no

  vimdiff file1_with_line_no file2_with_line_no

然后输出如您所愿(显示为diff,以便轻松复制到此处):

 diff file1_with_line_no file2_with_line_no --side-by-side
 1  foo 0.0000                                            |      1  foo 8.1047
 2  bar 5.3124                                            |      2  bar 6.2343
 3  foo 4.5621                                            |      3  foo 0.0000
 4  bar 6.3914                                            |      4  bar 1.4452
 5  foo 1.0000                                                   5  foo 1.0000
 6  bar 6.3212                                            |      6  bar 7.2321

在 bash 中,您可以将其添加到您的 .bashrc,这样您就可以在命令行中使用 linediff 来正常调用两个文件之间的差异:

linediff() { 
     if [ -z "$1" ] || [ -z "$2" ]; then return; fi
     f1=$(basename "$1")
     f2=$(basename "$2")
     cat -n "$1" > "/tmp/$f1"
     cat -n "$2" > "/tmp/$f2"
     vimdiff "/tmp/$f1" "/tmp/$f2"
     rm "/tmp/$f1" "/tmp/$f2"
 }

现在linediff file1 file2 将执行上述操作并在之后进行清理。

【讨论】:

  • 感谢您的建议。如果 vimdiff 中确实没有这样的功能,那么对于我的特定情况(在这种情况下我不需要编辑文件)来说,这实际上是一个足够好的解决方法。不过,我仍然希望使用后者,因为一旦我想编辑差异文件,这种解决方法就会中断。
  • 好的,所以我已经通过man diff,但似乎没有这样的选择......我唯一至少尝试过的是-d(@ 987654332@ 似乎也是如此),它显然使用了一些更复杂的算法来最小化差异(尽管没有提供任何进一步的细节),但至少对于我在问题中的例子来说它没有改变任何东西。跨度>
  • 这太棒了,我将它包装在一个 bash 函数中。希望您不介意我将其添加到您的问题中。谢谢!
【解决方案2】:

使用diffchar.vim 插件怎么样?它在非差异模式下逐行比较。请在 2 个窗口上打开 2 个文件,然后按 F7。默认情况下,它会尝试通过一行中的字符来查找差异,但您可以更改差异单位、单词或其他内容。

【讨论】:

  • 哇,这个插件太棒了!除了在非差异模式下运行它确实完全符合我的要求(这就是为什么我除了你的答案之外),它通过将差异突出显示减少到实际差异来大大提高 vimdiff 整体!我一直很恼火的是,如果一行上有两个差异,这些差异之间的整个区域都会突出显示,而不仅仅是实际差异,例如使用重命名的变量或沿着该行的东西扫描两个代码的差异极大地复杂化,这个插件完全解决了这个问题。非常感谢!
  • @RickHowe,你的插件是必备插件!
  • 自插件版本 8.0 起,此解决方案不再有效。 @rick-howe,有解决方法吗?
  • diffchar.vim 自 8.0 起现在仅适用于差异模式。请上传github.com/rickhowe/sample/blob/master/mylinediff.vim 设置diffexpr 选项并逐行检查内容。不要忘记在两个窗口上执行 'diffthis'。
【解决方案3】:

Vim 依赖外部diff 命令来分析这两个文件,因此您可以通过使用不同算法的不同工具来影响结果。您可以通过'diffexpr' 选项进行配置;该工具的输出必须采用“ed”样式。 CP。 :help diff-diffexpr.

请注意,这只影响添加/更改/删除的行;为了在更改的行本身中显示字符差异,Vim 自己完成。

不幸的是,我不知道任何替代差异工具可以提供这样的输出,但也许其他人可以填补。

【讨论】:

  • 感谢指向 diffexpr 的指针。我已经很确定 vimdiff 只是在后台使用 diff,现在我知道在哪里寻找。您是否知道diff 足以确定此功能不存在(或者您现在只是偶然知道它)? (我想我应该一头扎进man diff...)
猜你喜欢
  • 2020-06-11
  • 1970-01-01
  • 2017-04-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-09-23
  • 2018-10-26
相关资源
最近更新 更多