无法在Vim中搜索重复的句子

时间:2009-04-19 11:23:07

标签: search vim

我在Vim的搜索模式

中运行以下失败
^(\1) (\2)

我试图在我的.vimrc中找到两个第一个单词相同的行。

如何在Vim中搜索这些行?

[在第一个回答后编辑]

我找到了方便的工具

:sort u

如何在命令后比较我的第一个版本和后续版本?

4 个答案:

答案 0 :(得分:2)

你有点暧昧。

  • 如果您想查找第二个单词重复第一个单词的行,例如
      dog dog this line
      dog cat not this line
      cat cat this line
      cat dog not this line
    
    然后使用以下正则表达式:
      /^\s*\(\w\+\)\s\+\1
    
    第一个单词由\(\w\+\)捕获,并通过反向引用再次匹配\1

  • 如果您想按前两个单词对行进行分组,例如

      a a is the first line in group 'a a'
      a b is the first line in group 'a b'
      a b is the second line in group 'a b'
      -------------nogroup---------------
      a b is the third line in group 'a b'
      b b is the first line in group 'b b'
      a b is the fourth line in group 'a b'
           b b is the second line in group 'b b'
    
    ,那么:sort就是您的朋友。但是,如果你只是运行:sort,你会得到这个:
           b b is the second line in group 'b b'
      -------------nogroup---------------
      a a is the first line in group 'a a'
      a b is the first line in group 'a b'
      a b is the fourth line in group 'a b'
      a b is the second line in group 'a b'
      a b is the third line in group 'a b'
      b b is the first line in group 'b b'
    
    注意组'a b'中的第四行如何放在第一行之后,第二行放在第一行之后 由于前导空格,'b b'首先放置。这是因为:sort, 默认情况下,使用整行。要使它只按前两个单词排序,并保留 否则,使用:sort /^\s*\zs\w\+\s\+\w\+/ r
      -------------nogroup---------------
      a a is the first line in group 'a a'
      a b is the first line in group 'a b'
      a b is the second line in group 'a b'
      a b is the third line in group 'a b'
      a b is the fourth line in group 'a b'
      b b is the first line in group 'b b'
           b b is the second line in group 'b b'
    
    ^\s*\zs告诉它忽略前导空格,\w\+\s\+\w\+告诉它使用第一个 两个单词作为排序键。 r选项告诉:sort使用给定的 模式作为排序键。有关更多信息,请参阅:help :sort

    如果你想看看改变了什么,我可以想到两种策略来帮助你:

    • 您可以保存文件,对行进行排序,然后将副本保存为其他名称,然后使用vim的内置差异功能来比较两者:
      :w                                 "save your file
      :sort /^\s*\zs\w\+\s\+\w\+/ r      "sort it by the first two words
      :w %.sorted                        "save the sorted version in a new file with a .sorted extension
      :undo                              "undo your changes to the original
      :vs %.sorted                       "open the sorted version in a new window
      :windo diffthis                    "compare the two versions
      
      但是,这可能无法为您提供非常有用的反馈。

    • 可能会给您提供更有用的反馈的是在排序前插入行号,这样您就可以看到原始文件中的行号到了哪里。为此,请尝试以下操作:
      :%s/^/\=line('.') . ' '
      :sort /^\d\+\s*\zs\w\+\s\+\w\+/ r
      
      %s/^/\=line('.') . ' '在每行的开头插入行号。然后排序(稍微修改以忽略行号)就可以了。对于上面的例子, 这会产生:
      4 -------------nogroup---------------
      1 a a is the first line in group 'a a'
      2 a b is the first line in group 'a b'
      3 a b is the second line in group 'a b'
      5 a b is the third line in group 'a b'
      7 a b is the fourth line in group 'a b'
      6 b b is the first line in group 'b b'
      8      b b is the second line in group 'b b'
      
      所以现在你知道哪条线来自哪里。

答案 1 :(得分:1)

您的意思是:removing duplicate lines

答案 2 :(得分:1)

我找不到简短的vim风格解决方案。这就是为什么这里是vim脚本。

function! s:escape(line)
    return escape(a:line, '[]*')
endfunction

function! s:highlight_similar(pattern, extraction)
    let sorted = sort(getline(1, '$'))
    let matched_lines = {}

    let pattern = '^\s*\(\w\+\)\s\+\(\w\+\).*$'
    let previous_part = ''
    let previous_line = ''

    for i in range(0, line('$') - 1)
        let line = sorted[i]
        if line !~ a:pattern
            continue
        endif
        let part = substitute(line, a:pattern, a:extraction, '')
        if empty(part)
            continue
        endif
        if part == previous_part
            let matched_lines[s:escape(line)] = i
            let matched_lines[s:escape(previous_line)] = i
        else
            let previous_part = part
            let previous_line = line
        endif
    endfor
    let @/ = join(keys(matched_lines), '\|')
endfunction

命令定义应该在同一个文件中

command! -nargs=0 HighlightTwoWords
      \call <SID>highlight_similar('^\s*\(\w\+\)\s\+\(\w\+\).*$', '\1 \2')
command! -nargs=0 HighlightTwoRows
      \call <SID>highlight_similar('^\s*\(.*\)\s*$', '\1')

然后在使用'HighlightTwoWords'命令后,您将能够使用'n'和'N'来移动您感兴趣的行。或者通过使用'hls [earch]'命令,您可以突出显示这些行。 / p>

答案 3 :(得分:1)

你的意思是:找到前两个单词相同的任何一行吗?

试试这个:

/ ^(\ w +)\ 1

或更一般地

/ ^(\ W +)\ S \ 1