【问题标题】:How can I mark/highlight duplicate lines in VI editor?如何在 VI 编辑器中标记/突出显示重复的行?
【发布时间】:2009-08-12 18:53:03
【问题描述】:

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

之前:

foo
bar
foo
baz

之后:

foo*
bar
foo*
baz

【问题讨论】:

    标签: vim duplicates


    【解决方案1】:

    作为前单行:

    :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// 的搜索中删除突出显示

    Justin 的非正则表达式方法可能更快:

    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()
    

    【讨论】:

    • 非正则表达式方法快如闪电!很好的脚本,谢谢!
    • 这真是太棒了!
    • 我无法让它工作。我已经将该函数放在我的 ~/.vimrc 中,但是当我运行 ":call HighlightRepeats()" 时出现错误:处理函数 HighlightRepeats 时检测到错误:第 10 行:E28:没有这样的高亮组名称:重复
    • Daps0l:尝试将hi link Repeat Statement 添加到您的~/.vimrc
    • 感谢打破它!
    【解决方案2】:

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

    1. 使用:sort对文件进行排序
    2. 执行命令:g/^\(.*\)$\n\1$/p

    【讨论】:

    • 谢谢。我觉得这是更好的方法。有了这个,我们可以找到重复的行以及自定义到所需的长度
    • 我喜欢这多么简单!
    • 我需要帮忙解释一下。 g 全局命令(在这种情况下从上到下遍历每一行)^\(.*\)$ 捕获整行...\nnewline 字符...\1$ 和上一行(到end) 这部分只是检查下一行是否与当前行相同。但是为什么我的 Vim 会突出显示多个单独的事件,p(粘贴)是干什么用的?
    • @Ari:p 用于“打印”。实际上你可以删除它,因为它是默认命令。不确定“为什么我的 Vim 会突出显示多个单独的事件”是什么意思。 Vim 应该突出显示/打印重复的行。
    • 尝试使用vim -u NONE 并打开一个带有结果的拆分窗格。在这种情况下,我理解您所说的 print 是什么意思。我的一个插件用突出显示的行显示了这个imgur.com/a/6Qu8Q65。在我的另一个 Vim 实例上,它没有显示底部拆分,而是仅突出显示行。
    【解决方案3】:
    1. :sort 并将其保存在 file1 中。
    2. :sort u 并将其保存在 file2 中。
    3. gvimdifftkdiff 这两个文件。

    【讨论】:

      【解决方案4】:

      为什么不使用:

      V*
      

      在正常模式下。

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

      n
      

      浏览比赛

      【讨论】:

      • 视觉模式默认不支持*。这可能是您的 .vimrc 中的一个功能。像这样的东西: xno * :calVisualSearch()/ xno # :calVisualSearch()? 有趣! s:VisualSearch() let old = @" | norm! gvy let @/ = '\V'.substitute(escape(@", '\'), '\n', '\\n', 'g')让@" = 旧 endf)
      • Arg,格式搞砸了。这就是我的意思:pastebin.com/f2ee37c92
      • 一次只能匹配一件事,而我更愿意同时指出与其他行重复的所有行。不过功能不错,看起来很方便。
      【解决方案5】:

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

      【讨论】:

        【解决方案6】:

        试试:

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

        希望这行得通。

        更新:下次尝试。

        :%s:^\(.\+\)$\(\_.\+\)^\1$:\1\r\2\r\1*:
        

        【讨论】:

        • 这只会检测相邻的重复行,并且只会标记第一个副本,而不是第二个。
        猜你喜欢
        • 1970-01-01
        • 2017-04-04
        • 2015-02-16
        • 1970-01-01
        • 1970-01-01
        • 2019-07-11
        • 1970-01-01
        • 2014-10-23
        • 1970-01-01
        相关资源
        最近更新 更多