Vim 进阶教程

发布于:2025-07-28 ⋅ 阅读:(17) ⋅ 点赞:(0)

文本替换 (: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 没有匹配项,不报错(抑制错误信息)。

常见示例:
  • 替换当前行第一个 foobar:s/foo/bar/

  • 替换当前行所有 foobar:s/foo/bar/g

  • 替换整个文件中所有 foobar (全局替换): :%s/foo/bar/g

  • 替换第 10 行到第 20 行所有 foobar:10,20s/foo/bar/g

  • 替换整个文件中所有 foobar,但每次替换前确认: :%s/foo/bar/gc

  • 将文件中所有 colorcolour 替换为 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 使用自己的变种,但基础与其他类似)。

  • 分隔符 / 可替换: 如果 oldnew 中包含 /,可以用其他字符作为分隔符,如 :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 文件中替换 oldnew: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$ (tcopy 的缩写,$ 表示文件末尾)。

    • 在包含 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-commentarygc 快速注释)

  • 环绕编辑:
    vim-surroundcs"' 替换双引号为单引号)

  • 自动补全:
    coc.nvimLSP 支持)

  • 项目目录树浏览、文件管理。
    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 只保存修改过的文件


网站公告

今日签到

点亮在社区的每一天
去签到