他の行の正確な複製であるバッファー内のすべての行にどのようにマークを付けますか?マークすることで、ハイライトしたり、キャラクターや何かを追加したりします。バッファ内の行の順序を保持したい。
変更前:
foo
bar
foo
baz
後:
foo*
bar
foo*
baz
元ワンライナーとして:
_: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()
_
上記の答えのどれも私にとってうまくいかなかったので、これは私がしていることです:
:sort
_を使用してファイルを並べ替えます:g/^\(.*\)$\n\1$/p
:sort
をfile1
に保存します。:sort u
をfile2
に保存します。gvimdiff
またはtkdiff
2つのファイル。なぜ使用しない:
V*
通常モードで。
現在の行のすべての一致を検索し、それらを強調表示するだけです(設定が有効になっている場合は、これがデフォルトだと思います)。
n
マッチをナビゲートするには
試してください:
:%s:^\(.\+\)\n\1:\1*\r\1:
これがうまくいくことを願っています。
更新:次の試み。
:%s:^\(.\+\)$\(\_.\+\)^\1$:\1\r\2\r\1*:
リストを1回実行し、各文字列とそれが発生した回数のマップを作成します。もう一度ループして、マップで複数の値を持つ文字列に*を追加します。