如何在 Vim/Neovim 中复制多行文本并批量替换相同内容?
可以。先把需要替换的多行文本 yank 到寄存器,转换成搜索模式后执行 :%s。这样不用为每个文本块手写正则表达式,也不用安装插件。
1. 复制完整的列表表达式
在普通模式下,将光标放到 foo([ 中的 [ 上,输入:
"ay%
这会将从 [ 到对应 ] 的内容复制到寄存器 a,包括中间的换行,但不包括外层的 foo( 和 )。
对于其他形状的表达式,可以用字符可视模式 v 选中完整内容,再输入 "ay。应避免使用整行可视模式 V,否则可能把函数名、外层括号或末尾换行一起复制进去。
2. 将寄存器内容转换为搜索模式
在同一行输入并执行以下命令:
:let @/ = '\V\C' . substitute(escape(@a, '\'), "\n", '\\n', 'g')
其中:
@a是刚才复制的文本。escape(@a, '\')转义原文本中的反斜杠,避免它们被解释为正则指令。substitute(..., "\n", '\\n', 'g')将实际换行转换为匹配模式中的\n。\V启用 very nomagic,使方括号、圆括号、点号等按字面匹配。\C强制区分大小写。@/是搜索寄存器,用来保存生成的模式。
在 \V 下,反斜杠仍有特殊含义,因此不能省略转义;跨行匹配需要保留表示行边界的 \n。这些规则见 Vim 搜索模式文档。
3. 批量替换为变量名
接着执行:
:%s//my_vars/gc
命令中省略了匹配模式,会直接使用刚设置的搜索模式。% 表示整个文件,g 在默认设置下替换每行内的所有匹配,c 要求逐个确认。确认时按 y 替换当前匹配,按 n 跳过,按 a 替换所有剩余匹配。空模式的复用规则和确认标志见 Vim 替换命令文档。
如果不需要逐个确认,可以使用:
:%s//my_vars/g
执行前不要插入其他搜索操作,以免覆盖刚设置的搜索模式。
4. 添加变量定义
先完成替换,再添加变量定义,避免新定义中的列表也被替换为 my_vars。
寄存器 a 仍保存着原列表。先将它粘贴到文件顶部:
:0put a
再给第一行加上赋值前缀:
:1s/^/my_vars = /
根据需要添加空行后,结果如下:
my_vars = [
"var1",
"var2",
"var3",
]
foo(my_vars)
bar(my_vars)
:put 会按整行方式插入寄存器内容,因此可以把以字符方式复制的列表作为独立代码块插入。具体行为见 Vim 的
注意匹配范围
这个方案按文本匹配,空格、缩进和换行位置都需要一致。内容相同但格式不同的表达式不会自动视为同一个匹配。
替换操作不会分析作用域或程序语义。提取后应确保 my_vars 在调用处可见;如果列表会被修改,还需要确认多个调用共享同一个列表是否符合预期。
如果把替换内容改成其他字符串,替换侧的 &、反斜杠和分隔符仍需按 :substitute 的规则处理,\V 只控制匹配侧。
备注:内容仅供参考。
