71

您将如何标记缓冲区中与其他行完全相同的所有行?通过标记它们,我的意思是突出它们或添加字符或其他东西。我想保留缓冲区中行的顺序。

前:

foo
bar
foo
baz

后:

foo*
bar
foo*
baz
4

6 回答 6

103

作为前单行:

:syn clear Repeat | g/^\(.*\)\n\ze\%(.*\n\)*\1$/exe 'syn match Repeat "^' . escape(getline('.'), '".\^$*[]') . '$"' | nohlsearch

这使用Repeat组来突出显示重复的行。

分解它:

  • syn clear Repeat:: 删除任何以前发现的重复
  • g/^\(.*\)\n\ze\%(.*\n\)*\1$/:: 对于文件中稍后重复的任何行
    • 正则表达式
      • ^\(.*\)\n:: 整行
      • \ze:: 匹配结束 - 验证模式的其余部分,但不要使用匹配的文本(正向前瞻)
      • \%(.*\n\)*:: 任意数量的完整行
      • \1$:: 匹配的整行的整行重复
    • exe 'syn match Repeat "^' . escape(getline('.'), '".\^$*[]') . '$"':: 将与此匹配的完整行添加到Repeat语法组
      • exe:: 将给定的字符串作为 ex 命令执行
      • getline('.'):: 当前行的内容匹配g//
      • escape(..., '".\^$*[]'):: 用反斜杠转义给定的字符以生成合法的正则表达式
      • syn match Repeat "^...$":: 将给定的字符串添加到Repeat语法组
  • nohlsearch:: 从已完成的搜索中删除突出显示g//

贾斯汀的非正则表达式方法可能更快:

function! HighlightRepeats() range
  let lineCounts = {}
  let lineNum = a:firstline
  while lineNum <= a:lastline
    let lineText = getline(lineNum)
    if lineText != ""
      let lineCounts[lineText] = (has_key(lineCounts, lineText) ? lineCounts[lineText] : 0) + 1
    endif
    let lineNum = lineNum + 1
  endwhile
  exe 'syn clear Repeat'
  for lineText in keys(lineCounts)
    if lineCounts[lineText] >= 2
      exe 'syn match Repeat "^' . escape(lineText, '".\^$*[]') . '$"'
    endif
  endfor
endfunction

command! -range=% HighlightRepeats <line1>,<line2>call HighlightRepeats()
于 2009-08-13T08:07:08.473 回答
65

上面的答案都不适合我,所以这就是我所做的:

  1. 使用排序文件:sort
  2. 执行命令:g/^\(.*\)$\n\1$/p
于 2015-02-24T08:08:56.790 回答
17
  1. :sort并将其保存在file1.
  2. :sort u并将其保存在file2.
  3. gvimdifftkdiff这两个文件。
于 2017-05-10T06:36:20.220 回答
3

为什么不使用:

V*

在正常模式下。

它只是搜索当前行的所有匹配项,从而突出显示它们(如果启用了设置,我认为这是默认设置)此外,您可以使用

n

浏览比赛

于 2009-08-17T06:00:26.803 回答
2

遍历列表一次,制作每个字符串的映射以及它出现的次数。再次循环遍历它,并将您的 * 附加到映射中值大于 1 的任何字符串。

于 2009-08-12T19:00:55.363 回答
2

尝试:

:%s:^\(.\+\)\n\1:\1*\r\1:

希望这有效。

更新:下次尝试。

:%s:^\(.\+\)$\(\_.\+\)^\1$:\1\r\2\r\1*:
于 2009-08-13T04:58:57.493 回答