您可以将该: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','')#
概述
>>>
捕获和<<<
标记之间的文本(包括空格) 。将文本两边的空白分成两半,并用中间的非空白文本替换。这种空白平衡行为是通过正则表达式引擎的回溯完成的,因为数学很难。我们去购物吧!
笔记:
- 使用
\v
orvery 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*$
匹配非空白(即<<<
)和任何尾随空白
- 使用
\zs
andze
指定要替换的比赛的开始和结束
替换
\=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
在末尾添加以禁用突出显示。
如果执行这个命令,它看起来像: