Vim 进阶教程

文本替换 (: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 按语法折叠)

显示不可见字符

查看空格、制表符、换行符等:

shell 复制代码
:set list  " 显示不可见字符($表示换行,^I表示制表符)
:set nolist  " 关闭显示

标记 (Marks):

  • 快速跳转到文件中的特定位置。

  • 设置标记: m + <letter> (例如 ma 设置标记 a)。

  • 跳转到标记:

xml 复制代码
` + <letter>

(反引号,例如 `a 精确跳转到标记 a 的行和列) 或

vbnet 复制代码
' + <letter>

(单引号,例如 'a 跳转到标记 a 所在行的行首)。

  • 查看标记: :marks

  • 特殊标记:

    • ``:跳回上次跳转前的位置。

    • '.:上次修改的行。

    • '^:上次插入模式退出的位置。

会话管理 (Sessions)

  • 保存会话(打开的文件、窗口布局等):
shell 复制代码
:mksession ~/session.vim
  • 恢复会话:
shell 复制代码
vim -S ~/session.vim

外部命令与管道

  • Vim 中执行 shell 命令并将结果导入缓冲区:
shell 复制代码
:r !ls -l
  • 对选中区域执行外部命令:
shell 复制代码
:'<,'>!sort

将选区内内容按 sort 排序。

自动命令 (autocmd):

  • 在特定事件发生时自动执行命令,用于高度定制 Vim 行为(如文件类型检测、保存时自动格式化等)。这属于更高级的 .vimrc 配置。

  • 基本示例 (在 .vimrc 中):

vim 复制代码
" 当打开或新建 .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:

  • 精确全文替换:
shell 复制代码
:%s/\<user_id\>/user_id_new/gc
  • 如果涉及多个文件:
shell 复制代码
:argdo %s/\<user_id\>/user_id_new/ge | update

关键点:

  • \<\> 匹配单词边界(避免匹配 _user_id_old

  • /e 屏蔽未匹配时的报错

  • | update 只保存修改过的文件

相关推荐
小白跃升坊24 分钟前
基于1Panel的AI运维
linux·运维·人工智能·ai大模型·教学·ai agent
跃渊Yuey42 分钟前
【Linux】线程同步与互斥
linux·笔记
舰长1151 小时前
linux 实现文件共享的实现方式比较
linux·服务器·网络
zmjjdank1ng1 小时前
Linux 输出重定向
linux·运维
路由侠内网穿透.1 小时前
本地部署智能家居集成解决方案 ESPHome 并实现外部访问( Linux 版本)
linux·运维·服务器·网络协议·智能家居
VekiSon1 小时前
Linux内核驱动——基础概念与开发环境搭建
linux·运维·服务器·c语言·arm开发
Hello World . .2 小时前
数据结构:栈和队列
c语言·开发语言·数据结构·vim
zl_dfq2 小时前
Linux 之 【进程信号】(signal、kill、raise、abort、alarm、Core Dump核心转储机制)
linux
Ankie Wan2 小时前
cgroup(Control Group)是 Linux 内核提供的一种机制,用来“控制、限制、隔离、统计”进程对系统资源的使用。
linux·容器·cgroup·lxc
skywalk81632 小时前
尝试在openi启智社区的dcu环境安装ollama最新版0.15.2(失败)
linux·运维·服务器·ollama