文本替换 (:s)
这是 Vim 中最强大和最常用的进阶功能之一。
基本语法: :[range]s/old/new/[flags]
[range]: 指定替换操作的范围。省略时默认为当前行。%:整个文件 (例如:%s/old/new/)5,10:第5行到第10行 (例如:5,10s/old/new/).,$:从当前行到文件末尾 (例如:.,$s/old/new/).+1,$-1:从当前行下一行到文件倒数第二行/pattern1/,/pattern2/:从匹配pattern1的行到匹配pattern2的行'<,'>:当前选中的可视区域(在可视模式下按:后自动填充)
s: substitute (替换) 命令。old: 要被替换的文本(模式)。支持正则表达式! (这是它强大的核心)new: 替换成的新文本。[flags]: 控制替换行为的标志(可选,可组合使用)。g (global): 对一行内的所有匹配项进行替换(默认只替换一行中的第一个匹配项)。非常重要!c (confirm): 每次替换前要求确认。按y替换,n跳过,a替换所有,q退出替换。i (ignore case): 忽略大小写进行匹配。I (no ignore case): 区分大小写进行匹配(默认行为)。e (no errors): 如果old没有匹配项,不报错(抑制错误信息)。
常见示例:
- 替换当前行第一个
foo为bar::s/foo/bar/ - 替换当前行所有
foo为bar::s/foo/bar/g - 替换整个文件中所有
foo为bar(全局替换)::%s/foo/bar/g - 替换第 10 行到第 20 行所有
foo为bar::10,20s/foo/bar/g - 替换整个文件中所有
foo为bar,但每次替换前确认::%s/foo/bar/gc - 将文件中所有
color或colour替换为hue(忽略大小写)::%s/colou\?r/hue/gi(这里\?表示前面的u可有可无,i忽略大小写) - 删除所有行尾的空白字符:
:%s/\s\+$//g(\s\+匹配一个或多个空白字符,$匹配行尾) - 删除所有行首的空白字符:
:%s/^\s\+//g(^匹配行首) - 将
"name"替换为'name'::%s/"$$[^"]*$$"/'\1'/g(使用捕获组$$...$$和反向引用\1) - 在变量名后添加
_v2(捕获组\1)::%s/\<\(\w\+\)\>/\1_v2/g
重要提示:
- 正则表达式是核心: 要充分利用
:s,必须学习基础的正则表达式 (Vim使用自己的变种,但基础与其他类似)。 - 分隔符
/可替换: 如果old或new中包含/,可以用其他字符作为分隔符,如:s#old#new#g或:s@old@new@g。 - 先确认 (
c标志): 对于全局替换 (:%s/...),尤其是在生产代码中,强烈建议使用c标志先检查确认。 - 查看匹配: 在输入
:s/old后,按Ctrl-R Ctrl-W(在命令模式下) 可以将光标下的单词插入到命令中。在替换前使用/old搜索一下,用:nohl取消高亮,可以直观看到哪些地方会被匹配。
批量操作/多文件操作
多行编辑(可视化块模式)
结合 Ctrl + v(垂直选中)实现批量添加 / 删除前缀 / 后缀:
批量给多行添加前缀(如注释符号
//):- 按
Ctrl + v进入垂直选择模式 - 移动光标选中需要操作的行(如向下按
j选 5 行) - 按
I(大写I,进入插入模式),输入前缀(如//) - 按
ESC,所有选中行都会添加前缀
- 按
批量删除多行前缀:
Ctrl + v选中需要删除的前缀列(如前 2 个字符)- 按
d直接删除选中的列
argdo / bufdo / windo / tabdo:
- 这些命令允许在多个参数列表文件(
argdo)、缓冲区(bufdo)、窗口(windo)、标签页(tabdo) 上执行相同的Ex命令。 示例:
- 打开多个文件:
vim *.txt 在所有打开的
.txt文件中替换old为new::argdo %s/old/new/ge | update%s/old/new/ge:在每个文件内执行全局替换 (g),忽略错误 (e防止没有匹配的文件报错退出)。| update:管道符|连接命令,update仅在文件被修改过时才保存。
- 在所有打开的缓冲区中执行替换并保存:
:bufdo %s/old/new/ge | w
- 打开多个文件:
- 注意:
argdo操作的是:args列表中的文件,bufdo操作的是所有加载到缓冲区的文件。
:vimgrep / :grep:
- 在整个项目文件中搜索包含特定模式的行。
:vimgrep /pattern/[j][g] file(s)/pattern/:搜索模式(支持Vim强大的正则)。[j]:不跳转到第一个匹配项(静默搜索)。[g]:每行只列出一次匹配(默认列出每行的所有匹配)。file(s):文件模式,如**/*.py递归搜索所有.py文件。- 示例:
:vimgrep /TODO/ **/*.py(在所有.py文件中搜索"TODO")
- 搜索结果会填充到
quickfix列表 (:copen打开列表,:cclose关闭,:cn下一个,:cp上一个)。 结合
:cdo/:cfdo::cdo command:对quickfix列表中的每一行执行命令 (光标会移动到对应行)。:cfdo command:对quickfix列表中的每一个文件执行命令 (光标会移动到对应文件)。强大示例: 在所有包含
"TODO"的.py文件中,将"TODO"替换为"FIXME"::vimgrep /TODO/ **/*.py:cfdo %s/TODO/FIXME/ge | update- 对每个匹配文件 (
:cfdo) 执行全局替换 (%s/.../g),忽略错误 (e),修改才保存 (update)。
宏录制 (q):
- 录制:
q + <register>(例如qa) 开始录制到寄存器a-> 执行你的操作序列 ->q停止录制。 - 播放:
@ + <register>(例如@a) 播放寄存器a中的宏。@@重复播放上一次播放的宏。 批量播放: 结合行号或可视选择。
:10,20 normal @a:对第 10 行到第 20 行的每一行,在普通模式下执行寄存器a中的宏。- 在可视模式下选中多行,然后按
:,会自动填充为:'<,'>,然后输入normal @a。
示例: 给一组连续的行添加注释 (
//):- 将光标移动到第一行的行首。
qa开始录制到a。I// <Esc>:进入插入模式,输入//,退出插入模式。j:移动到下一行。q:停止录制。- 按
@a对当前行执行宏(添加注释并下移一行)。 - 按
5@a重复执行 5 次宏(给接下来的 5 行添加注释)。或者用jVG选中剩余行,然后:'<,'>normal @a。
其他高级技巧
重复操作(.命令)
. 可以重复上一次的编辑操作,是 Vim 最被低估的技巧之一:
- 例 1:删除一行后,按
.会重复删除下一行 - 例 2:在某行末尾添加
;,按.会在其他行末尾重复添加
快速跳转与定位
按内容跳转:
*:向下跳转到当前单词的下一个匹配#:向上跳转到当前单词的上一个匹配
跳转到上次编辑位置:
''(两个单引号):跳回上一次跳转前的位置.(点符号):跳转到上次编辑的位置
global 命令 (:g):
- 对匹配特定模式的行执行命令。
- 语法:
:[range]g/pattern/command 示例:
- 删除所有空行:
:g/^$/d(匹配行首^紧接着行尾$的行,即空行,执行d删除)。 - 删除所有包含
DEBUG的行::g/DEBUG/d - 将所有包含
TODO的行复制到文件末尾::g/TODO/t$(t是copy的缩写,$表示文件末尾)。 - 在包含
function的行前面添加注释::g/function/normal O// TODO: Implement
- 删除所有空行:
全局反向操作(:vglobal)
:v/^$/d:删除所有非空行
寄存器 (") 的高级使用:
| 寄存器 | 含义 |
|---|---|
" | 默认寄存器,存放最近一次的删除或复制 |
0 | 存放最近一次的复制(y 命令) |
1–9 | 最近 9 次删除操作 (滚动存放) |
a–z | 用户自定义寄存器,可用 "ayy 复制到 a |
/: | 存放最近一次的搜索模式 |
指定寄存器: 在操作命令前加上
"<register>。"ayy:复制当前行到寄存器a。"bdd:删除当前行到寄存器b(剪切)。"ap:粘贴寄存器a的内容。
- 查看寄存器内容:
:reg或:reg <register>(如:reg a)。 系统剪贴板 (
"+ / "*): 设置了clipboard=unnamed,通常"+和"*都指向系统剪贴板。显式使用:"+yy:复制当前行到系统剪贴板。"+p:粘贴系统剪贴板内容到Vim。
只读寄存器:
"%:当前文件名。".:上次插入的文本。"::上次执行的命令。"/:上次搜索的模式。
折叠代码
zc:折叠当前代码块(如函数、循环)zo:展开当前折叠块zR:展开所有折叠zM:折叠所有代码块
(需先设置折叠方式:set foldmethod=indent 按缩进折叠,或 set foldmethod=syntax 按语法折叠)
显示不可见字符
查看空格、制表符、换行符等:
:set list " 显示不可见字符($表示换行,^I表示制表符)
:set nolist " 关闭显示标记 (Marks):
- 快速跳转到文件中的特定位置。
- 设置标记:
m + <letter>(例如ma设置标记a)。 - 跳转到标记:
` + <letter>(反引号,例如 `a 精确跳转到标记 a 的行和列) 或
' + <letter>(单引号,例如 'a 跳转到标记 a 所在行的行首)。
- 查看标记:
:marks。 特殊标记:
- ``:跳回上次跳转前的位置。
- '.:上次修改的行。
- '^:上次插入模式退出的位置。
会话管理 (Sessions)
- 保存会话(打开的文件、窗口布局等):
:mksession ~/session.vim- 恢复会话:
vim -S ~/session.vim外部命令与管道
- 在
Vim中执行shell命令并将结果导入缓冲区:
:r !ls -l- 对选中区域执行外部命令:
:'<,'>!sort将选区内内容按 sort 排序。
自动命令 (autocmd):
- 在特定事件发生时自动执行命令,用于高度定制
Vim行为(如文件类型检测、保存时自动格式化等)。这属于更高级的.vimrc配置。 - 基本示例 (在
.vimrc中):
" 当打开或新建 .py 文件时设置缩进
autocmd BufNewFile,BufRead *.py setlocal tabstop=4 shiftwidth=4 expandtab
" 保存 .py 文件前自动删除行尾空白
autocmd BufWritePre *.py :%s/\s\+$//e窗口和标签页管理:
分割窗口:
:split / :sp [filename]:水平分割当前窗口(或打开文件)。:vsplit / :vsp [filename]:垂直分割当前窗口(或打开文件)。Ctrl-w s:水平分割。Ctrl-w v:垂直分割。Ctrl + w + =:让所有分屏高度 / 宽度相等
- 窗口间跳转:
Ctrl-w h/j/k/l/Ctrl-w w(循环)。 - 关闭窗口:
:close/Ctrl-w c。 - 调整窗口大小:
Ctrl-w +/Ctrl-w -(高度),Ctrl-w >/Ctrl-w <(宽度)。 标签页:
:tabnew [filename]:在新标签页打开文件。:tabclose:关闭当前标签页。:tabnext / gt:下一个标签页。:tabprevious / gT:上一个标签页。:tabm [n]:移动当前标签页到位置n(从 0 开始计数)。
命令行窗口 (q:):
- 普通模式下按
q:打开命令行窗口。这里显示命令历史,可以像编辑普通文本一样浏览、修改历史命令,然后按回车执行选中的命令。非常方便修改复杂命令(如带复杂正则的:s命令)。 表达式寄存器 (
=):- 在插入模式下按
Ctrl-r =,可以输入一个 Vim 表达式(如2+2或@a),计算结果会插入到文本中。高级用法可以结合函数。
- 在插入模式下按
normal命令 (:normal):- 在命令行模式下执行普通模式的命令序列。
示例:
- 在当前行执行宏
a::normal @a - 在选中的行(可视模式后)删除行首空白:
:'<,'>normal ^dW(先跳到行首非空字符^,然后删除一个单词dW,这里空白被当作一个单词)。
- 在当前行执行宏
符号自动补全 (
Ctrl-x系列):在插入模式下:
Ctrl-x Ctrl-l:整行补全。Ctrl-x Ctrl-f:文件名补全。Ctrl-x Ctrl-o:全能 (Omni) 补全(需要文件类型支持,如编程语言)。Ctrl-n / Ctrl-p:使用当前缓冲区中的单词补全。
自动缩进 (
=):- 在可视模式下选中代码块,按
=会自动缩进(根据文件类型和你的indent设置)。 gg=G:对整个文件进行自动缩进 (gg到文件头,=缩进操作,G到文件尾)。
- 在可视模式下选中代码块,按
高级配置技巧(需修改.vimrc)
高效搜索
set incsearch:输入搜索词时实时高亮匹配set hlsearch:高亮所有搜索结果,用:nohl临时关闭高亮
文件管理
set autochdir:自动切换工作目录到当前文件位置set wildmenu:增强文件名补全(按Tab循环选择)
备份与撤销
set undodir=\~/.vim/undo:持久化撤销历史(支持关闭文件后仍可撤销)
代码格式化
filetype indent on:根据文件类型自动缩进set tabstop=4:设置Tab为4空格
插件推荐(进阶工具)
- 多文件搜索:
fzf.vim(模糊搜索文件/内容) - 批量注释:
vim-commentary(gc快速注释) - 环绕编辑:
vim-surround(cs"'替换双引号为单引号) - 自动补全:
coc.nvim(LSP支持) - 项目目录树浏览、文件管理。
nerdtree 实时显示
Git diff(新增、修改、删除行)vim-gitgutter / signify
其他示例
将项目中的 user_id 改为 user_id_new:
- 精确全文替换:
:%s/\<user_id\>/user_id_new/gc- 如果涉及多个文件:
:argdo %s/\<user_id\>/user_id_new/ge | update关键点:
\<和\>匹配单词边界(避免匹配_user_id_old)/e屏蔽未匹配时的报错| update只保存修改过的文件
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用。你还可以使用@来通知其他用户。