这是一个“oneliner”(几乎),但您必须为每个唯一的行减去 1 重做它,在您的示例中为 2 次。也许没有用,但我认为这是一个很好的练习,可以更多地了解 VIM 中的模式。只要整行是唯一的,它就可以处理所有类型的行(例如,mno 和 mnp 是两个唯一的行)。
首先确保这一点(并且不将/ 映射到任何东西,或该行中的任何其他东西):
:set nowrapscan
然后映射例如这些(应该是递归的,不是nnoremap):
<C-R>和<CR>应该按字面意思输入。
\v 在模式中意味着“非常神奇”,@! 负前瞻。 \2 使用第二个括号中的内容。
:nmap ,. "xy$/\v^<C-R>x$<CR>:/\v^(<C-R>x)@!(.*)$\n(\2)$/m-<CR>j,.
:nmap ,, gg,.
然后尽可能多地执行,,,在您的示例中为 2 次。一个适用于所有bs,一个适用于所有cs。
编辑:映射说明。我将使用问题中的示例,就好像它已经使用此映射运行了一次一样。
一次运行后:
1. a
2. b
3. a
4. b
5. a
6. b
7. c
8. c
9. c
然后光标在最后一个a(第5行),当输入,,时,它首先回到第一行,然后为,.运行映射,这个映射是这样做的:
"xy$ # yanks current line (line 1) to reg. "x" ("a") "
/\v^<C-R>x$<CR> # finds next line matching reg. "x" ("a" at line 3)
:/\v^(<C-R>x)@!(.*)$\n(\2)$/m-<CR>
# finds next line that have a copy under it ("c" in line 7) and moves that line
# to current line (to line 3, if no "-" #after "m" it's pasted after current line)
# Parts in the pattern:
- ^(<C-R>x)@!(.*)$ # matches next line that don't start with what's in reg. "x"
- \n(\2)$ # ...and followed by newline and same line again ("c\nc")
- m-<CR> # inserts found line at current line (line 3)
j # down one line (to line 4, where second "a" now is)
,. # does all again (recursive), this time finding "c" in line 8
...
,. # gives error since there are no more repeated lines,
# and the "looping" breaks.