您可以将该:s命令与\=aka sub-replace-expression 一起使用。
:s#\v^\s*\S+\zs(\s+)(.{-})(\s+)\ze\S+\s*$#\=substitute(submatch(1).submatch(3),'\v^(\s*)(\1\s=)$','\1'.escape(submatch(2),'~&\').'\2','')#
概述
>>>捕获和<<<标记之间的文本(包括空格) 。将文本两边的空白分成两半,并用中间的非空白文本替换。这种空白平衡行为是通过正则表达式引擎的回溯完成的,因为数学很难。我们去购物吧!
笔记:
- 使用
\vorvery magic模式来减少转义,因为这个命令已经足够长了
- 用作
#替代分隔符而不是通常/的 for:s/pat/sub/以使其更具可读性
匹配模式
:s#\v^\s*\S+\zs(\s+)(.{-})(\s+)\ze\S+\s*$#...
:s如果没有提供范围,则仅在当前行上进行替换。
^\s*\S+匹配起始空白,后跟非空白。>>>在这种情况下。
(\s+)(.{-})(\s+)匹配空格后跟“文本”后跟空格
- 3 个捕获组:1)前导空白,2)“文本”,以及 3)尾随空白。这些将在稍后分别由
submatch(1)、submatch(2)和引用submatch(3)
.{-}是 vim-speak 用于非贪婪匹配或.*?perl-speak
- 如果没有非贪婪匹配,第二个捕获组将在其末尾包含太多空白
\S+\s*$匹配非空白(即<<<)和任何尾随空白
- 使用
\zsandze指定要替换的比赛的开始和结束
替换
\=substitute(submatch(1).submatch(3),'\v^(\s*)(\1\s=)$','\1'.escape(submatch(2),'~&\').'\2','')
\=告诉 vim 替换将是一个 vim 表达式。还允许使用submatch()函数
substitute({str}, {pat}, {sub}, {flags})我们的表达式将是一个嵌套替换
substitute(submatch(1).submatch(3), ...)submatch(1)对在和中捕获的前导和尾随空白的串联进行替换submatch(3)
{pat}是^(\s*)(\1\s=)$。_ 匹配一些空格,后跟与第一个或 1 个字符长度相同的空格。捕获两半。
escape(submatch(2),'~&\')任何特殊字符的转义submatch(2)。例如~, &, \1, ...
{sub}是'\1'.escape(submatch(2),'~&\').'\2'。_ 替换submatch(2)为空格之间的转义(即我们想要居中的“文本”),\1并\2从{pat}
- 不需要
{flag},所以''
用法
如果您经常使用它,我建议您创建一个命令并将其放入~/.vimrc.
command! -range -bar -nargs=0 CenterBetween <line1>,<line2>s#\v^\s*\S+\zs(\s+)(.{-})(\s+)\ze\S+\s*$#\=substitute(submatch(1).submatch(3),'\v^(\s*)(\1\s=)$','\1'.submatch(2).'\2','')#`
否则使用一次,然后&在每个需要的行上重复最后一次替换。
如需更多帮助,请参阅
:h :s/
:h :s/\=
:h sub-replace-\=
:h submatch(
:h substitute(
:h escape(
:h /\v
:h /\S
:h /\{-
:h /\zs
:h &
肯特编辑
不要嫉妒,你的答案也有。^_^
我没有更改命令,只是 cp/paste 到我的 vim。仅|noh在末尾添加以禁用突出显示。
如果执行这个命令,它看起来像:
