1. 为什么今天还值得花时间学vi说句实话在2025年还在教学vi听起来确实有点像在教人用算盘。但如果你真的在命令行环境里工作过哪怕一个星期你就会明白vi从来就没有退出过历史舞台它只是安静地躺在每一台Linux服务器的某个角落里等着你某天SSH上去改配置时不得不面对它。我最早接触vi是被逼的。当时要给一台无图形界面的服务器改nginx配置手边只有PuTTY窗口nano都没装输入vi /etc/nginx/nginx.conf之后界面进了但我完全不知道该怎么输入文字。光标在闪键盘敲了半天没有任何反应我一度以为是服务器卡死了。后来才知道vi默认处于命令模式你敲的字母不是在输入文字而是在输入命令。这种设计在今天看来确实反直觉但一旦理解它的底层逻辑就会发现vi的效率远超大多数现代编辑器。这篇内容不是什么权威教程更像是我把自己用过vi这几年踩过的坑、养成的习惯、以及带新人时反复讲的东西做一次系统梳理。不追求面面俱到但保证你读完能解决两个最核心的痛点第一能在vi里自如地编辑文件而不被卡住第二理解vi的设计思维让它真正成为你的工具而不是拦路虎。无论你是运维工程师、后端开发、数据分析师还是偶尔需要在服务器上改个配置的普通程序员这篇文章都适用。我会从模式概念讲到高频命令再到真实场景中的完整操作流程最后说几个我自己摸索出来的、网上很多教程不会写的小技巧。2. vi的两个模式真相先解决怎么退出这个世纪难题2.1 模式化设计的底层逻辑打开vi的一瞬间你面对的不是一个空白的输入框而是一个处于待命状态的编辑器。这是vi与Windows记事本、macOS TextEdit等模态化编辑器最本质的区别。几乎所有新手都问过同一句话我怎么退出vi这个问题的根源就在于不理解模式的存在。vi有且仅有两种核心模式命令模式和插入模式。命令模式是vi的默认状态也是它的主战场。在这个模式下你敲下的每一个键都被解释为命令——j代表向下移动光标x代表删除当前字符dd代表删除整行。这不是为了折磨新手而是为了让你双手不离开键盘主区域就能完成所有编辑操作。插入模式才是真正输入文字的状态。进入插入模式的方式有很多种最常见的按i键。一旦进入插入模式vi的行为就和普通编辑器基本一致你可以正常打字、删除、换行。按Esc键则返回命令模式。这个设计的巧妙之处在于编辑文本这个动作其实包含了两类完全不同性质的操作——指挥命令和输入内容。传统编辑器把这两者混在一起你必须额外使用鼠标、菜单、快捷键组合比如CtrlC、CmdS来区分。vi干脆用模式把它们彻底分开让你在命令模式里高效指挥在插入模式里专注输入。就像开车一样方向盘是方向盘油门是油门模式本身就是一种防呆设计。提示新手最常见的困境就是忘记自己在哪个模式。记住一句话就够了——看到屏幕左下角显示INSERT就是插入模式没显示就是在命令模式。2.2 退出vi完整手册网上有个经久不衰的段子Stack Overflow上面浏览量最高的问题之一就是How do I exit the Vim editor。这背后是无数人真实的崩溃体验。这里直接把退出方案列全你以后不管遇到什么状态都能找到对应的出口。正常退出文件已保存确保在命令模式按Esc输入:q然后回车需要保存修改后退出在命令模式输入:wq然后回车无论怎么改都不想保存强制退出在命令模式输入:q!然后回车保存但不退出命令模式输入:w然后回车如果进入了一些奇怪的状态屏幕状态原因恢复正常的方法左下角显示INSERT处于插入模式按Esc回到命令模式左下角显示:开头的信息处于末行模式按Esc取消显示E37: No write since last change有未保存修改:q!强制退出显示E32: No file name文件还没命名:w 文件名指定名称保存进入了Ex模式屏幕底部出现:提示符误按Q键输入:visual回车恢复这套表基本覆盖了99%的卡死场景。我的建议是作为新手Esc键是你的逃生通道不管你在什么状态连按两下Esc通常都能回到命令模式的安全地带。2.3 从vi是什么到实践的最小闭环如果你在服务器上只想做一件最简单的事——打开文件、改一行内容、保存退出完整流程是这样的vi /etc/hosts进入文件后光标停在第一行。假设你要改第一行的IP地址按i进入插入模式光标前插入把IP地址修改好按Esc退回命令模式输入:wq回车保存并退出就这么简单。等你完整跑通这个流程vi的学习就算迈过了最大的门槛。剩下的所有操作都是在命令模式下的快捷操作和插入模式下的不同进入方式上面做文章。3. 命令模式才是vi的灵魂移动、删除、撤销一篇讲透3.1 光标的四向移动与跳跃式定位很多人用了vi好几年翻页还是靠方向键移动还是靠长按↓。这虽然能完成任务但和vi的设计初衷背道而驰。vi在命令模式下提供了极其高效的字符级移动方案核心键位是h左、j下、k上、l右。这组键位把右手食指和小指的移动范围控制在最小半径内让你不必把右手从主键区挪到方向键区长期下来速度差异相当明显。不过真正拉开效率差距的是vi的跳跃式移动w跳到下一个单词的开头b跳到当前单词或上一个单词的开头e跳到当前单词的末尾0跳到当前行行首^跳到当前行第一个非空白字符$跳到当前行行尾gg跳到文件第一行G跳到文件最后一行Ctrl f向下翻一页Ctrl b向上翻一页/关键词搜索n跳到下一个匹配N跳到上一个匹配这些移动命令的重要性我怎么强调都不过分。我见过有人用vi改一个500行的配置文件光是滚动光标就花了5分钟而熟练者用gg跳头部、G跳尾部、/关键词直接定位全程不超过30秒。差别不在手速在于是否理解vi把移动当成一种检索行为而不是滚动行为。技巧数字命令是vi中非常强大的组合。比如输入5j光标向下跳5行输入3w向右跳3个单词。这对熟悉排版的人来说极其直观好像英文写作里数着词移动一样。3.2 删除不再用退格键命令模式下的删除操作让你彻底摆脱长按退格键的噩梦x删除光标所在位置的字符X删除光标前面的字符dd删除当前整行d$删除从光标位置到行尾的所有内容d0删除从光标位置到行首的所有内容dw删除光标所在单词5dd从当前行开始向下删除5行如果删除操作做错了别慌u撤销上一步操作Ctrl r重做撤销的撤销vi的撤销粒度和普通编辑器不同。普通编辑器通常按字符撤销vi按命令撤销。你执行了一次dd删除整行按一次u就整行恢复。这个设计在某些场景下是优势比如你误删了一大段代码一次u就全部回来。但也意味着当你在插入模式下连续输入了500个字再按u这500个字会一次性被撤销掉。如果你只想要撤销最后几个字需要进入命令模式再手动处理。3.3 复制粘贴与搜索替换复制粘贴在vi中叫做yank和put因为操作概念来自物理世界——掰下一段放在别处。yy复制当前行yw复制当前单词p粘贴到光标之后/下一行取决于复制的是字符还是整行P粘贴到光标之前/上一行复制粘贴组合起来的典型场景你有一段重复的配置要写三次先yy复制第一段然后光标移到第二个位置按p粘贴再移到第三个位置再按一次。注意vi的粘贴默认使用一个名为无名寄存器的暂存区也就是说你复制的文本会覆盖之前复制的文本没有历史记录。不过vi真正强大的地方在于命名寄存器a到z后面我会细讲。搜索替换是vi的高频操作之一语法遵循末行命令的格式:s/旧文本/新文本/ 替换当前行第一个匹配 :s/旧文本/新文本/g 替换当前行所有匹配 :%s/旧文本/新文本/g 替换整个文件所有匹配 :%s/旧文本/新文本/gc 逐个确认替换会逐个询问 :2,10s/旧文本/新文本/g 替换第2行到第10行我在改代码里的大批量节点名时最常用的就是:%s/oldname/newname/g这条命令。它等价于很多IDE里的全文件查找替换但不需要鼠标操作输入完一回车就完事。如果担心误替换加c参数逐条确认这在公开文本里替换时相当有用。3.4 进阶移动可视块选择与多文件编辑vi还有一个宝藏功能——可视模式Visual Mode。在命令模式下按v进入字符可视模式按V进入行可视模式按Ctrl v进入块状可视模式。块状可视模式最为惊艳它允许你像在Excel里拖动框选一样选中任意矩形区域的文本。选中后可以执行d删除选中的块y复制选中的块I在选中的每一行开头插入相同内容先按I输入内容后按Esc这个批量行首插入功能简直是我们改配置文件的救星比如说给20行注释加#前缀无需一行行改直接块选这20行的开头按I输入#回车20行一次性搞定。操作路径Ctrl v进入块模式方向键选中多行开头区域按I输入内容按Esc。停这里有个坑——输入内容后必须按Esc修改才会应用到所有选中的行。我一开始不知道这个细节输入完直接移动方向键结果只改了一行。这种怪异行为让新手相当困惑但一旦记住这个先用Esc确认的逻辑之后就顺手了。多文件编辑也是被很多人忽略的功能。vi可以同时打开多个文件用:e 文件名在当前窗口打开新文件用:n切换到下一个文件。如果你有3个文件需要同步修改可以在启动时直接写好vi file1.txt file2.txt file3.txt然后用:n依次切换。如果担心改动丢失用:wall一次性保存所有文件再用:qall全部退出。这比开多个终端窗口省事多了。4. 插入模式的下车方式i、I、a、A、o、O之间的细微差别4.1 六个入口实用场景各有不同插入模式有六个主要入口命令它们决定了你在插入前光标如何定位。理解这几个键的差异能让你的操作精准得像墙上打孔一样——不多一分不少一毫。i在光标当前位置前插入。最常用进入插入模式后直接在当前位置开始打字。I在当前行行首插入。适合在行首添加代码或注释前缀。a在光标当前位置后插入。比如你想在括号后面补一个参数光标还在括号里按a光标跳到括号后面再进入插入模式。A在当前行行尾插入。这个是最常用但最容易被忽视的因为它省去了先按$跳行尾再按i两步操作直接A一步到位。o在当前行下方另起一行并进入插入模式。适合在代码块之间新增一行。O在当前行上方另起一行并进入插入模式。逻辑和o相反。这六个键的规律其实很好记小写是光标当前位置附近大写是行首或行尾的意思更远一步i和a是在光标前后插入I和A是沿行首行尾插入o和O是另起新行插入。4.2 插入模式中的拼写与回退进入插入模式后很多人会习惯性地按方向键移动光标这没有问题。但有一个小坑在插入模式下按退格键Backspace不一定能删除上一个字符。vi中有一项设置叫backspace默认仅允许删除光标之前的内容如果你在插入模式下想删除行首的字符就会发现退格键没有反应。解决方案是在vimrc中配置set backspaceindent,eol,start这个配置允许在行首、行尾以及缩进区域使用退格键删除内容体验上与普通编辑器一致。注意这是vim的设置vi本身可能不支持但绝大多数现代Linux系统的vi命令其实都指向了vim。在纯vi环境下如果配置不生效你仍然可以按Esc回到命令模式用x删除单个字符。4.3 一个容易混淆的细节在插入模式下执行一次命令键盘上Ctrlo这个组合在vi的插入模式下有一种神奇的效果它让你临时执行一条命令执行完成后再自动返回插入模式。比如你在插入模式编辑到一半突然想起要看看文件路径正常步骤是Esc、:pwd、回车、再按i回去。但用Ctrlo可以直接在插入模式中输入:pwd回车然后自动回到插入模式光标位置不变输入状态不被打断。这像在驾驶途中临时看仪表盘然后手自动回到方向盘上。这个技巧非常实用但网上很少提到我自己是用了大半年才偶然在一个论坛帖子里看到的。5. 从vi到vim现代开发者的必备配置5.1 vi、vim、neovim的关系很多人会问我明明输入的是vi为什么终端显示的是VIM在现代Linux发行版中vi通常是一个指向vimVi Improved的符号链接或替代程序。vim在vi的基础上增加了无数功能语法高亮、多级撤销、可视化操作、插件系统等。而neovim是vim的一个现代化分支项目采用新的代码架构支持更灵活的配置语言和异步执行能力。对普通用户而言你学的主角vi和vim的基本操作完全一致迁移零成本。查看当前实际使用的版本命令是vim --version如果系统里只有vi没有vim在Debian系可以用apt install vim安装在RHEL系可以用dnf install vim-enhanced。5.2 一份推荐的基础vimrc配置如果你觉得vi的默认界面偏冷淡一步一步优化即可。以下是一份经过实践验证的配置能大幅提升体验同时不改变vi的基本操作逻辑 不兼容vi的经典模式启用vim增强特性 set nocompatible 显示行号 set number 显示相对行号当前行为0上下行为1、2... set relativenumber 语法高亮 syntax on 自动识别文件类型并启用插件缩进 filetype plugin indent on 使用4个空格代替制表符 set expandtab set tabstop4 set shiftwidth4 显示匹配的括号 set showmatch 搜索时高亮所有匹配 set hlsearch 边输入边搜索 set incsearch 启用鼠标支持在终端中拖动选择 set mousea 允许退格键跨行删除 set backspaceindent,eol,start 开启系统剪贴板需要vim编译时支持clipboard set clipboardunnamedplus 显示当前文件名和状态 set laststatus2 编码设置为UTF-8 set encodingutf-8这份配置的每个选项几乎都对应一种让vi更像现代编辑器但又保留其灵魂的折中方案。注意clipboard这一行如果你的vim没有编译剪贴板支持用vim --version检查输出中是否有clipboard则该配置不生效。解决办法是安装vim-gtk或vim-gui-common这类带图形支持的版本。5.3 插件从基础到进阶如果你要长期使用vim进行代码开发插件是绕不开的话题。搭建一个简单的插件管理系统在vim 8.0以上版本可以用内置的包管理器在~/.vim/pack/目录下创建子目录然后把插件克隆进去vim启动时自动加载。最经典的三件套nerdtree文件树侧边栏按F9显示文件列表ctrlp快速文件搜索按Ctrlp后输入文件名立即跳转vim-airline美化状态栏显示模式、分支、行列号安装示例mkdir -p ~/.vim/pack/plugins/start git clone https://github.com/preservim/nerdtree.git ~/.vim/pack/plugins/start/nerdtree但我个人更推荐先不用插件至少用纯vi操作一两个月把这个编辑器的思维方式真正内化。如果一开始就装了文件树、代码补全这些重型插件很容易陷入用vim模拟IDE的误区反而失去了它轻灵的本性。工具是给人用的合适就够了不用整一堆花活。6. 实操手记用vi完成一次真实的服务器配置修改纸上谈兵到这里我决定用一个完整的实操场景串起前面所有知识点。情境你新接了一台服务器需要修改SSH服务的端口号假设从默认的22改成22022同时排查一个定时任务的配置问题。6.1 第一阶段定位与进入vi /etc/ssh/sshd_config文件打开后命令模式待命。先查看当前有多少个Port配置:/Port按n连续查找发现默认的#Port 22被注释了。我们需要把它取消注释并修改。光标定位到这一行执行^跳到行首非空白字符按x删除开头的#按A跳到行尾输入22022按Esc最后:wq保存退出。这里用到的A键非常顺手一次解决跳行尾进入插入模式两个操作。如果不知道这个组合就得先按$再按i多两步。6.2 第二阶段验证与错误处理当然改完配置必须重启服务并验证ss -tlnp | grep 22022如果报错说端口被SELinux拦截还需要调整SELinux端口规则。这种场景下我会用vi打开SELinux的配置文件快速查看vi /etc/selinux/config把SELINUXenforcing改为SELINUXdisabled这属于生产环境的新手操作实际上生产环境改SELinux需要谨慎评审但这里仅作为演示vi用法。执行gg跳文件头/SELINUX搜索关键词光标到达后按ciw修改整个单词这个组合后面会讲输入disabledEsc:wq。6.3 第三阶段批量修改与多文件操作接着排查某个定时任务脚本这个脚本有多个文件都包含旧的日志路径/var/log/oldapp/需要全部改成/var/log/neyapp/。此时多文件编辑就派上用场了vi /etc/cron.d/backup /etc/cron.d/cleanup /etc/cron.d/sync在当前文件执行:%s#/var/log/oldapp/#/var/log/neyapp/#g注意我用#作为分隔符而不是/这是因为替换内容本身就包含/用#可以避免转义地狱。这是vi中的一个小技巧替换命令的分隔符可以是任意字符只要内容里不冲突即可。然后输入:n切换到下一个文件同样执行替换最后:wall保存所有文件:qall退出。整套操作一气呵成全程不需要鼠标五秒都不到。6.4 第四阶段崩溃恢复——意外关闭后的救援这里必须单独提一节因为vi的崩溃恢复机制是每个运维人迟早需要用的。假设你正在编辑一个重要文件突然终端卡死、SSH断连或者你直接把窗口关掉了再次打开文件时会看到E325: ATTENTION Found a swap file by the name .sshd_config.swp这意味着vim检测到上一次编辑会话没有正常结束产生了交换文件swap file。你可能记不清自己改了什么或者想恢复那些未保存的修改处理方式如下如果上次的修改还需要输入RRecover即可恢复到交换文件中的版本然后:wq保存。如果确定不需要上次的修改输入DDelete删除那个交换文件再正常打开原文件。如果想坚持用普通方式打开文件输入q退出先手动处理交换文件。交换文件一般以.文件名.swp形式存在于同目录下。恢复完成后记得检查并删除它否则vi每次打开这个文件都会报警告。注意有了这个机制很多人在没保存的情况下直接关终端会手足无措。其实vi已经帮你保存了大部分输入到交换文件里只要不随便删.swp数据大概率是能找回来的。7. 组合命令与实战心得从会用到用得顺到这一步如果你已经掌握了上面提到的命令基本日常操作是没有问题了。但会用和用得顺之间还有一段距离关键在于组合。7.1 复合指令动词数字移动vi命令的精髓在于操作符范围的组合。操作符包括d删除、y复制、c修改范围可以是字符、单词、行、整个文件。当两者结合时威力倍增ciw修改当前光标所在的完整单词Change Inner Word。光标在单词中间时ciw直接删掉整个单词并进入插入模式等你输入新内容。改变量名、改API函数名时非常常用。dw删除当前单词c$从光标位置改到行尾ct,从光标位置改到下一个逗号前t表示直到某个字符前di(删除括号内的所有内容不包含括号本身da(删除包括括号在内的内容y3w复制后面的3个单词dgg从当前位置删除到文件头部这些组合看起来复杂规律其实朴素动词d/y/c 范围i/a/t/数字 对象w/s/括号等 字符。理解了这层语法几乎能推导出所有的组合命令。有点像学吉他先记住和弦形状再练习转换最后手指形成肌肉记忆。7.2 宏录制把重复操作交给vi宏录制Macro是真正考验vi功力的功能。它允许你录制一系列操作然后在需要的地方回放。场景驱动假设一个1000行的文本文件中每行末尾都要加一个;而且第5行到第10行还需要特殊处理。手工操作会烦死人宏一键搞定。录制步骤在命令模式按q然后按a定义一个名为a的宏寄存器屏幕左下角出现recording提示执行操作按$跳到行尾按a进入插入模式输入;按Esc按q停止录制把光标移到下一行按a回放宏如果要对所有行执行可以这样:%normal a这条命令把宏a应用到文件的每一行。录一次、用百遍这种批量操作带来的爽感是很多编辑器无法给到的。心得宏录制时注意不要录制跳转类命令如G、gg、/搜索因为回放时会破坏位置。尽量录制当前光标附近的修改然后用移动命令逐行调用。7.3 排除两个高频误解有一个高频卡顿场景新手在vim里执行了:tabnew打开新标签页之后发现按什么键都无法关闭新标签界面毫无反应。实际上关闭标签的命令是:q或:tabclose。这个误会源于对vim窗口、缓冲区buffer、标签页tab概念的混淆。理解buffer是内存中的文件副本窗口是buffer的显示区域标签页是窗口的容器。操作时要清楚自己在操作哪个对象。另一个高频误解是关于Ctrls冻结终端。在终端中Ctrls默认是暂停输出XOFF很多人想用Ctrls做保存结果发现终端整个卡住按什么键都没反应。这是终端控制字符不是vim的行为。按下Ctrlq可以解除冻结。建议保存一律用:w。7.4 实用心得vi学习路径拆解总结一个适合大多数人的学习路径按阶段走不焦虑第一周只记i进插入、Esc回命令、:wq保存退出、dd删行。能在vi里改文件就够用。第二周记w、b、$、0四个移动命令删除加移动全面替换gg、G首尾跳转。第三周理解ciw、di(等复合命令开始用/搜索跳转。一个月左右开始配置vimrc逐渐加入相对行号、系统剪贴板等选项。两三个月尝试宏录制、多文件编辑并逐渐形成自己的默认配置。学vi最大的敌人是退回舒适区。很多人第一天用Escape键被卡住就果断放弃了然后回到nano或sublime。这太可惜了。因为熟练vi之后你在任何一台服务器上都能拥有相同的编辑体验无需安装任何东西。这份能力一旦获得就不会丢失。8. 遭遇vi报错时不要慌常见错误信息解读最后一步我结合前面提到的实际工况整理一份vi相关报错排查表。很多新手遇到error信息就慌尤其是网上那些自动抓出来的标题党信息其实一半是vi的正常机制一半是被语言包安装报错这类不相关问题误导了。8.1 vi自身的常见错误报错信息含义处理办法E32: No file name文件没有名字用:w 文件名命名保存E37: No write since last change有修改未保存:w保存或:q!放弃修改E212: Cant open file for writing没有写权限检查目录权限必要时sudo viE138: Cant write viminfo file无法写入历史记录文件检查~/.viminfo权限或空间E325: ATTENTION检测到交换文件按上文所述处理E486: Pattern not found搜索/替换的模式不存在检查拼写确认内容确实存在8.2 一个容易被误认为是vi报错的常见情况看这类网络热词搜到过error while installing chinese (simplified) (简体中文) language pack for vi的信息——这个报错本质上不是vi编辑器本身的问题而是某些IDE比如VS Code在安装简体中文语言包时因为网络代理、插件市场访问不稳定或者版本不兼容导致的插件安装失败。报错里出现了vi字样让很多人误以为vi出问题了。如果你遇到这个错误请记住这不是系统vi的问题你仍然可以正常使用vi编辑文件处理方法检查IDE的代理设置、重试安装、或者更新IDE版本在某些受限环境下可以手动下载语言包离线安装完全不值得为此影响你对vi的学习这种同名关键词引起的误判在技术领域很常见。排查问题时要先确认问题上下文不要被错误信息中的关键词误导。比如vi编辑器遇到问题时报错往往发生在打开文件、写入文件、切换缓冲区这几个环节而IDE装语言包报错发生在插件管理器层面。差别一目了然。8.3 从报错到解决一个完整个案例拿一个典型场景说明排查思路你在vi里执行:w保存文件结果看到E212: Cant open file for writing。这时候首先确认的不是vi坏了而是权限问题。处理步骤检查当前用户对文件是否有写权限ls -l 文件名检查文件所在目录是否有写权限ls -ld .如果确实没有权限用:w !sudo tee %这个经典技巧保存——它以sudo权限将当前缓冲区内容写入文件或者退出后直接用sudo vi 文件名打开重编辑。如果文件属于你自己但目录只读考虑是否需要调整目录权限。这类问题之所以让新手困惑是因为他们默认打开文件能编辑就能保存但Unix/Linux下能否打开和能否写入是两回事。vi作为一门老派工具其行为严格遵守操作系统的权限模型不会变通这也算是一种古老而质朴的确定性。9. 写在最后学习vi是值得的长期投资我最初学习vi时也充满挫败感Escape键按了无数遍模式切换的折磨几乎劝退。但真当我用了一个多月后那种指尖碰到哪个键都是命令、无需经过鼠标和菜单中转的流畅感是其他编辑器完全替代不了的。特别是在远程服务器、Docker容器的环境里没有图形界面vi几乎是唯一稳定的编辑器。那些必须依赖鼠标的同学在那时只能手忙脚乱。我自己的使用习惯是日常写代码用现代IDE但改服务器配置、写快速脚本、查看日志文件全都是vi。它和IDE不是替代关系而是互补——一个擅长大规模重构和项目管理一个擅长快速修改和轻量操作。学vi那点时间成本在一次突发故障中抢救一个关键配置就可能全赚回来了。如果你能坚持到看完这一篇我觉得你至少已经理解了vi的核心哲学。接下来的路就是在真实使用中慢慢积累自己的命令组合。希望这12年里vi帮我省下的那些时间也能变成你的时间。分享一个我的习惯在终端的~/.bashrc里加一行EDITORvi此后git commit、crontab -e等命令都会默认用vi打开这是把vi融入工作流最简单的一步。试试看它会在你完全没有察觉的时候成为你最顺手的东西。