在(NeoVim)中复制多行并替换匹配项

编程语言 2026-07-11

我想在nvim中选取多行,然后把我复制的内容粘贴到 :%s,\V...,以替换文件中所有出现的文本为一个新的字符串。举例来说,

foo([
    "var1",
    "var2",
    "var3",
])

bar([
    "var1",
    "var2",
    "var3",
])

理想情况下会变成

my_vars = [
    "var1",
    "var2",
    "var3",
]

foo(my_vars)

bar(my_vars)

我知道在这种情况下,我可以只用对 :%s 编写某些表达式来实现,但我更倾向于避免这种做法,因为对于复杂的多行表达式,事情会变得非常乏味。

我知道可以使用类似 refactoring.nvim 的插件来提取变量,但这在这种场景下仅对单个可视区段有效,不能解决此处的问题。

解决方案

简单的部分

  1. 将光标放在 foo 上,执行 ci),剪下圆括号中的内容并将你带入插入模式。
  2. 输入 my_vars,退出插入模式。缓冲区应当看起来像这样:

``` foo(my_vars)

bar([ "var1", "var2", "var3", ]) `` 3. 使用O在当前行之上打开一行。 4. 将刚才输入的名字按顺序插入="`,以插入刚才剪切的列表,并退出插入模式。缓冲区应当看起来像这样:

``` my_vars = [ "var1", "var2", "var3", ] foo(my_vars)

bar([ "var1", "var2", "var3", ]) ```

路上的障碍

此时,你的列表仍然保存在未命名寄存器中,在命令行中很容易被插入:

:%s/<C-r>"

但很明显,这种方法行不通:

糟糕

将多行文本复制并放入命令行其实是可行的,但它不会给你一个用于替换的合适正则表达式模式。为此,你必须辛苦地转义各种特殊字符,直到得到一个有效的模式。并不有趣。

真正的启示

我经常要做类似的事情,因此在我的Vim之旅早期就把以下内容整理了出来。

  • 一个函数,用以从任意字符串中得到合适的模式的函数:

" return a representation of the selected text " suitable for use as a search pattern function! GetSelection(escaped) let old_reg = getreg("v") normal! gv"vy let raw_search = getreg("v") call setreg("v", old_reg) if a:escaped return substitute(escape(raw_search, '\/.*$^~[]'), "\n", '\\n', "g") endif return raw_search endfunction * 一个映射,用来精简上面的“路上的障碍”:

xnoremap <key> :<C-u>%s/<C-r>=GetSelection(1)<CR>/

因此,回到之前还没变复杂的地方:

my_vars = [
    "var1",
    "var2",
    "var3",
]
foo(my_vars)

bar([
     "var1",
     "var2",
     "var3",
])

我会…

  1. 使用可视模式选中列表,按 va[
  2. <key> 进入命令行模式,得到一个干净的占位符:

:%s/\[\n "var1",\n "var2",\n "var3",\n\]/ 3.输入替换文本:

:%s/\[\n "var1",\n "var2",\n "var3",\n\]/my_vars 4.再添加 "confirm" 标志,以跳过第一次匹配:

:%s/\[\n "var1",\n "var2",\n "var3",\n\]/my_vars/c

总的来看,看起来是这样的:

ci)
my_vars<Esc>
O<C-a> = <Cr>"<Esc>
va]<key>
my_vars/c<CR>
n
y
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章