web-dev-qa-db-ja.com

VIエディターで重複する行をマーク/ハイライトするにはどうすればよいですか?

他の行の正確な複製であるバッファー内のすべての行にどのようにマークを付けますか?マークすることで、ハイライトしたり、キャラクターや何かを追加したりします。バッファ内の行の順序を保持したい。

変更前:

foo
bar
foo
baz

後:

foo*
bar
foo*
baz
55
Brian Carper

元ワンライナーとして:

_: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()
_
78
rampion

上記の答えのどれも私にとってうまくいかなかったので、これは私がしていることです:

  1. _:sort_を使用してファイルを並べ替えます
  2. コマンドを実行する:g/^\(.*\)$\n\1$/p
37
Jenny O'Reilly
  1. :sortfile1に保存します。
  2. :sort ufile2に保存します。
  3. gvimdiffまたはtkdiff 2つのファイル。
6
user7989979

なぜ使用しない:

V*

通常モードで。

現在の行のすべての一致を検索し、それらを強調表示するだけです(設定が有効になっている場合は、これがデフォルトだと思います)。

n

マッチをナビゲートするには

3
Lonecat

試してください:

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

これがうまくいくことを願っています。

更新:次の試み。

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

リストを1回実行し、各文字列とそれが発生した回数のマップを作成します。もう一度ループして、マップで複数の値を持つ文字列に*を追加します。

2
Justin