Vim 技巧 - 用寄存器的内容替换
实际上,我们不必手动输入完整的替换字符串。如果某段文本已在当前文档中出现,我们可以先把它复制到寄存器,再通过传值或引用的方式将寄存器的内容应用至替换域。
当 substitute 命令的查找域为空时,Vim 做出了智能的选择。人们不禁会想,如果将替换域留空的话,substitute 命令也一样会重用上一次的字符串吧?但事实并非如此。将替换域留空,意味着 substitute 命令会用空的字符串替换每一处匹配。换句话说,所有的匹配都被删除了。
# 传值
通过输入 <C-r>{register}
,我们可以将寄存器的内容插入到命令行。假设我们已经复制了一些文本,如果要将它们粘贴到 substitute 命令的替换域,需要输入以下命令:
➾:%s//<C-r>0/g
当我们输入 <C-r>0
时,Vim 会把寄存器 0 的内容粘贴进来,这意味着我们可以在执行 substitute 命令之前对其进行一番检查。在大多数情况下,它工作得都很好,但也引入了新的问题。
如果寄存器 0 中的文本包含了在替换域中具有特殊含义的字符(例如&或~),我们必须手动编辑这段文本,对这些字符进行转义。另外,如果寄存器 0 包含多行文本,有可能在命令行上显示不全。
为了避免这些问题,我们可以在替换域中简单地引用某个寄存器,从而得到该寄存器的内容。
# 引用
假设我们已经复制了多行文本,并存放于寄存器 0 中。我们现在的目标是在 substitute 命令的替换域中使用这段文本。通过运行以下命令,可以做到这一点:
➾:%s//\=@0/g
替换域中出现的 \=
将指示 Vim 执行一段表达式脚本。在 Vim 脚本中,我们可以用 @{register}
来引用某个寄存器的内容。具体来说,@0
会返回复制专用寄存器的内容,而 @"
则返回无名寄存器的内容。因此,表达式 :%s//\=@0/g
表示 Vim 将会用复制专用寄存器的内容替换上一次的模式。
注:VSCodeVim 不支持此功能
# 比较
先看一下这条命令:
➾:%s/Pragmatic Vim/Practical Vim/g
再与以下命令序列进行比较:
➾:let @/='Pragmatic Vim'
➾:let @a='Practical Vim'
➾:%s//=@a/g
其中,:let @/='Pragmatic Vim'
是采用编程的方式输入查找模式,它等同于直接执行查找命令/Pragmatic Vim<CR>
(有一点不同,即运行:let @/='Pragmatic Vim'
不会在查找历史中留下任何记录)。
同样的道理,:let @a='Practical Vim'
表示设置 a 寄存器的内容。它等同于高亮选中“Practical Vim”并用 "ay
将选中的文本存入寄存器 a。
这两条 substitute 命令都完成同一件事,即把所有“Pragmatic Vim”替换为“Practical Vim”。但我们要考虑一下它们各自的影响。
第一种方法,会在命令历史中留下一项内容为:%s/Pragmatic Vim/Practical Vim/g
的记录,使人一目了然。在稍后的编辑过程中,如果我们意识到要重复这条命令的话,可直接从命令历史中调出该项记录,即可加以执行。总之,不会有什么意外发生。
而第二种方法,会在命令历史中留下一项内容为:%s//\=@a/g
的记录。这看上去是不是相当神秘呢?
试想一下,当我们首次运行 substitute 命令时,查找模式为“Pragmatic Vim”,而寄存器 a 包含文本“Practical Vim”。但是半小时之后,当前的查找模式可能已经被多次修改了,而且寄存器 a 也可能被其他内容所覆盖。因此,如果我们重复:%s//\=@a/g
命令的话,结果会与第一次执行这条命令时截然不同。
我们可以利用这一特点。首先,我们查找要操作的文本,并将替换的内容复制到寄存器 a 中。之后,我们可以重复调用命令:%s//\=@a/g
,而该命令会使用刚刚被赋值的 @/
和 @a
中的内容。接下来,我们可以查找新的文本,并复制新的替换字符串至寄存器 a。而当我们再次重复 :%s//\=@a/g
命令时,运行结果将会迥然不同。
此法不妨一试。你或许会爱上它,也可能会讨厌它。但无论哪种情况,都是不错的技巧。
- 01
- 搭配 Jenkins 实现自动化打包微前端多个项目09-15
- 02
- 自动化打包微前端多个项目09-15
- 03
- el-upload 直传阿里 oss 并且显示自带进度条和视频回显封面图06-05