Vim教程博大精深,本文更多属于自我理解性质,请悉知。
Vim的学习曲线非常陡峭,作者认为“面向操作学习Vim”是科学合适的学习途径,能够降低学习Vim的难度。具体来说,“Vim操作”被设计有详细用法,详细用法中涉及到了“适用模式,是否支持重复执行N次操作,限定范围形式,是否支持文本对象”等内容,“Vim操作”是核心,它串联了这些内容,跟学习使用Linux中“Linux命令”是核心一样。
可通过:help topic查看关于某个“topic”的帮助内容。
一、操作
1.1、模式切换
| 操作 | 简单描述 |
|---|---|
| i | 从普通模式切入插入模式,在当前光标处插入 |
| A | 从普通模式切入插入模式,在当前行行尾插入 |
| v | 从普通模式切入可视模式,按照字符选取 |
| V | 从普通模式切入可视模式,按照行选取 |
| 连续按Esc一次或者两次 | 从插入模式、命令模式、可视模式切回普通模式 |
1.2、移动
| 操作 | 简单描述 | 适用模式 | 是否支持重复执行N次操作 | 限定范围形式 | 是否支持文本对象 |
|---|---|---|---|---|---|
| gg | 定位到文件头部 | 普通模式,可视模式 | [普通]不支持 [可视]不支持 |
[普通]未探究 [可视]未探究 |
[普通]未探究 [可视]未探究 |
| G | 定位到文件尾部 | 普通模式,可视模式 | [普通]不支持 [可视]不支持 |
[普通]未探究 [可视]未探究 |
[普通]未探究 [可视]未探究 |
| NG | 定位到第N行 | 普通模式,可视模式 | [普通]不支持 [可视]不支持 |
[普通]未探究 [可视]未探究 |
[普通]未探究 [可视]未探究 |
| 0 | 定位到行首 | 普通模式,可视模式 | [普通]不支持 [可视]不支持 |
[普通]未探究 [可视]未探究 |
[普通]未探究 [可视]未探究 |
| ^ | 定位到行首第一个非空字符 | 普通模式,可视模式 | [普通]不支持 [可视]不支持 |
[普通]未探究 [可视]未探究 |
[普通]未探究 [可视]未探究 |
| $ | 定位到行尾 | 普通模式,可视模式 | [普通]不支持 [可视]不支持 |
[普通]未探究 [可视]未探究 |
[普通]未探究 [可视]未探究 |
| h | 左移一个字符 | 普通模式,可视模式 | [普通]支持 [可视]支持 |
[普通]未探究 [可视]未探究 |
[普通]未探究 [可视]未探究 |
| l | 右移一个字符 | 普通模式,可视模式 | [普通]支持 [可视]支持 |
[普通]未探究 [可视]未探究 |
[普通]未探究 [可视]未探究 |
| k | 上移一个字符 | 普通模式,可视模式 | [普通]支持 [可视]支持 |
[普通]未探究 [可视]未探究 |
[普通]未探究 [可视]未探究 |
| j | 下移一个字符 | 普通模式,可视模式 | [普通]支持 [可视]支持 |
[普通]未探究 [可视]未探究 |
[普通]未探究 [可视]未探究 |
| f<X> | 快速定位到本行当前光标右侧第一个X字符处 | 普通模式,可视模式 | [普通]支持 [可视]支持 |
[普通]未探究 [可视]未探究 |
[普通]未探究 [可视]未探究 |
| F<X> | 快速定位到本行当前光标左侧第一个X字符处 | 普通模式,可视模式 | [普通]支持 [可视]支持 |
[普通]未探究 [可视]未探究 |
[普通]未探究 [可视]未探究 |
| t<X> | 快速定位到本行当前光标右侧第一个X字符处左侧 | 普通模式,可视模式 | [普通]支持 [可视]支持 |
[普通]未探究 [可视]未探究 |
[普通]未探究 [可视]未探究 |
| T<X> | 快速定位到本行当前光标左侧第一个X字符处右侧 | 普通模式,可视模式 | [普通]支持 [可视]支持 |
[普通]未探究 [可视]未探究 |
[普通]未探究 [可视]未探究 |
| w | 右移一个单词,停在单词头 | 普通模式,可视模式 | [普通]支持 [可视]支持 |
[普通]未探究 [可视]未探究 |
[普通]未探究 [可视]未探究 |
| e | 右移一个单词,停在单词尾 | 普通模式,可视模式 | [普通]支持 [可视]支持 |
[普通]未探究 [可视]未探究 |
[普通]未探究 [可视]未探究 |
| b | 左移一个单词,停在单词头 | 普通模式,可视模式 | [普通]支持 [可视]支持 |
[普通]未探究 [可视]未探究 |
[普通]未探究 [可视]未探究 |
| % | 定位到匹配的括号处(包括“花括号{},圆括号(),方括号[]”,不包括“尖括号<>”) | 普通模式,可视模式 | [普通]不支持 [可视]不支持 |
[普通]未探究 [可视]未探究 |
[普通]未探究 [可视]未探究 |
| ]m | 快速定位到下一个方法的“{”字符处(方法体使用“{}”字符对定义) | 普通模式,可视模式 | [普通]支持 [可视]支持 |
[普通]未探究 [可视]未探究 |
[普通]未探究 [可视]未探究 |
| [m | 快速定位到上一个方法的“{”字符处(方法体使用“{}”字符对定义) | 普通模式,可视模式 | [普通]支持 [可视]支持 |
[普通]未探究 [可视]未探究 |
[普通]未探究 [可视]未探究 |
| Ctrl+f | 向下移动一页,即PageDown | 普通模式,可视模式 | [普通]未探究 [可视]未探究 |
[普通]未探究 [可视]未探究 |
[普通]未探究 [可视]未探究 |
| Ctrl+b | 向上移动一页,即PageUp | 普通模式,可视模式 | [普通]未探究 [可视]未探究 |
[普通]未探究 [可视]未探究 |
[普通]未探究 [可视]未探究 |
1.3、编辑
| 操作 | 简单描述 | 适用模式 | 是否支持重复执行N次操作 | 限定范围形式 | 是否支持文本对象 |
|---|---|---|---|---|---|
| u | 撤销操作 | 普通模式,可视模式(撤销选取并返回普通模式) | [普通]支持 [可视]不支持 |
[普通]未探究 [可视]未探究 |
[普通]未探究 [可视]未探究 |
| Ctrl+r | 反撤销操作 | 普通模式 | [普通]支持 | [普通]未探究 | [普通]未探究 |
| dd | 删除当前行 | 普通模式 | [普通]支持 | [普通]不支持 | [普通]不支持 |
| d | 删除字符 | 普通模式,可视模式(删除选取内容并退回到普通模式),命令模式 | [普通]不支持 [可视]不支持 [命令]不支持 |
[普通]操作End [可视]不支持 [命令]Range操作 |
[普通]支持 [可视]不支持 [命令]不支持 |
| x(即“dl”) | 删除字符 | 普通模式,可视模式(删除选取内容并退回到普通模式) | [普通]支持 [可视]不支持 |
[普通]不支持 [可视]不支持 |
[普通]不支持 [可视]不支持 |
| yy | 复制当前行 | 普通模式,可视模式(复制选取内容并退回到普通模式) | [普通]支持 [可视]支持 |
[普通]不支持 [可视]不支持 |
[普通]不支持 [可视]不支持 |
| y | 复制字符 | 普通模式,可视模式(复制选取内容并退回到普通模式),命令模式 | [普通]不支持 [可视]不支持 [命令]不支持 |
[普通]操作End [可视]不支持 [命令]Range操作 |
[普通]支持 [可视]不支持 [命令]不支持 |
| p | 在光标后粘贴 | 普通模式,可视模式(替换选取内容并退回到普通模式) | [普通]支持 [可视]支持 |
[普通]不支持 [可视]不支持 |
[普通]不支持 [可视]不支持 |
| r | 替换字符 | 普通模式,可视模式(替换选取内容并退回到普通模式) | [普通]支持 [可视]支持 |
[普通]不支持 [可视]不支持 |
[普通]不支持 [可视]不支持 |
| ~ | 字母大小写互换 | 普通模式,可视模式(转换选取内容并退回到普通模式) | [普通]支持 [可视]不支持 |
[普通]不支持 [可视]不支持 |
[普通]不支持 [可视]不支持 |
| gu | 切换字母为小写 | 普通模式,可视模式(转换选取内容并退回到普通模式) | [普通]支持 [可视]不支持 |
[普通]操作End [可视]不支持 |
[普通]支持 [可视]不支持 |
| gU | 切换字母为大写 | 普通模式,可视模式(转换选取内容并退回到普通模式) | [普通]支持 [可视]不支持 |
[普通]操作End [可视]不支持 |
[普通]支持 [可视]不支持 |
1.4、查找替换
| 操作 | 简单描述 | 适用模式 | 是否支持重复执行N次操作 | 限定范围形式 | 是否支持文本对象 |
|---|---|---|---|---|---|
| / | 查找 | 命令模式 | [命令]不支持 | [命令]未探究 | [命令]未探究 |
| ? | 反向查找 | 命令模式 | [命令]不支持 | [命令]未探究 | [命令]未探究 |
| n | 下一个查找命中 | 普通模式 | [普通]支持 | [普通]未探究 | [普通]未探究 |
| N | 下一个反向查找命中 | 普通模式 | [普通]支持 | [普通]未探究 | [普通]未探究 |
| *和# | 基于光标当前所在的单词作匹配,移动光标到下一个(或上一个)匹配单词(*是下一个,#是上一个,支持循环) | 普通模式 | [普通]支持 | [普通]未探究 | [普通]未探究 |
| :%s/from/to/gc | 全局替换,替换前询问 | 命令模式 | [命令]不支持 | [命令]Range操作 | [命令]未探究 |
1.5、书签跳转
| 操作 | 简单描述 | 适用模式 | 是否支持重复执行N次操作 | 限定范围形式 | 是否支持文本对象 |
|---|---|---|---|---|---|
| m<NAME> | 定义名为“NAME”的书签 | 普通模式,可视模式 | [普通]未探究 [可视]未探究 |
[普通]未探究 [可视]未探究 |
[普通]未探究 [可视]未探究 |
| ‘<NAME> | 跳转到名为“NAME”的书签指向行 | 普通模式,可视模式 | [普通]未探究 [可视]未探究 |
[普通]未探究 [可视]未探究 |
[普通]未探究 [可视]未探究 |
| `<NAME> | 跳转到名为“NAME”的书签指向字符 | 普通模式,可视模式 | [普通]未探究 [可视]未探究 |
[普通]未探究 [可视]未探究 |
[普通]未探究 [可视]未探究 |
| :marks | 查看所有书签 | 命令模式 | [命令]不支持 | [命令]未探究 | [命令]未探究 |
备注:
名为a-z的书签不支持跨文件跳转,名为A-Z的书签支持跨文件跳转,其他名称的书签不作探究。
1.6、文本对象操作
| 操作 | 简单描述 | 适用模式 | 是否支持重复执行N次操作 | 限定范围形式 |
|---|---|---|---|---|
| aw | 选取一个单词 | 可视模式,普通模式中置于另外一个操作后面(比如daw) | [普通]支持 [可视]支持 |
[普通]未探究 [可视]未探究 |
| as | 选取一个句子 | 可视模式,普通模式中置于另外一个操作后面(比如das) | [普通]支持 [可视]支持 |
[普通]未探究 [可视]未探究 |
| ap | 选取一个段落 | 可视模式,普通模式中置于另外一个操作后面(比如dap) | [普通]支持 [可视]支持 |
[普通]未探究 [可视]未探究 |
| a] | 选取一个[]结构 | 可视模式,普通模式中置于另外一个操作后面(比如da]) | [普通]支持 [可视]支持 |
[普通]未探究 [可视]未探究 |
| a) | 选取一个()结构 | 可视模式,普通模式中置于另外一个操作后面(比如da)) | [普通]支持 [可视]支持 |
[普通]未探究 [可视]未探究 |
| a} | 选取一个{}结构 | 可视模式,普通模式中置于另外一个操作后面(比如da}) | [普通]支持 [可视]支持 |
[普通]未探究 [可视]未探究 |
| a> | 选取一个<>结构 | 可视模式,普通模式中置于另外一个操作后面(比如da>) | [普通]支持 [可视]支持 |
[普通]未探究 [可视]未探究 |
| at | 选取一个<xxx></xxx>结构 | 可视模式,普通模式中置于另外一个操作后面(比如dat) | [普通]支持 [可视]支持 |
[普通]未探究 [可视]未探究 |
| a” | 选取一个””结构 | 可视模式,普通模式中置于另外一个操作后面(比如da”) | [普通]不支持 [可视]不支持 |
[普通]未探究 [可视]未探究 |
| a’ | 选取一个’’结构 | 可视模式,普通模式中置于另外一个操作后面(比如da’) | [普通]不支持 [可视]不支持 |
[普通]未探究 [可视]未探究 |
| a` | 选取一个``结构 | 可视模式,普通模式中置于另外一个操作后面(比如da`) | [普通]不支持 [可视]不支持 |
[普通]未探究 [可视]未探究 |
备注:
另外还有“i(w,s,p,],),},>,t,”,’,`)”,它与“a(w,s,p,],),},>,t,”,’,`)”大同小异。
1.7、文件
| 操作 | 简单描述 | 适用模式 | 是否支持重复执行N次操作 | 限定范围形式 | 是否支持文本对象 |
|---|---|---|---|---|---|
| :w | 保存 | 命令模式 | [命令]未探究 | [命令]未探究 | [命令]未探究 |
| :w! | 强制保存 | 命令模式 | [命令]未探究 | [命令]未探究 | [命令]未探究 |
| :q | 退出 | 命令模式 | [命令]未探究 | [命令]未探究 | [命令]未探究 |
| :q! | 强制退出 | 命令模式 | [命令]未探究 | [命令]未探究 | [命令]未探究 |
| :wq | 保存并退出 | 命令模式 | [命令]未探究 | [命令]未探究 | [命令]未探究 |
1.8、环境
| 操作 | 简单描述 | 适用模式 | 是否支持重复执行N次操作 | 限定范围形式 | 是否支持文本对象 |
|---|---|---|---|---|---|
| :set number/nonumber | 显示/取消显示行号 | 命令模式 | [命令]未探究 | [命令]未探究 | [命令]未探究 |
| :set list/nolist | 显示/取消显示特殊字符 | 命令模式 | [命令]未探究 | [命令]未探究 | [命令]未探究 |
| :set ic/noic | 在查找时,不区分/区分字母大小写 | 命令模式 | [命令]未探究 | [命令]未探究 | [命令]未探究 |
1.9、功能
| 操作 | 简单描述 | 适用模式 | 是否支持重复执行N次操作 | 限定范围形式 | 是否支持文本对象 |
|---|---|---|---|---|---|
| ga | 显示光标所在字母的ASCII编码值,表示形式有十进制,十六进制和八进制 | 普通模式 | [普通]未探究 | [普通]未探究 | [普通]未探究 |
| Ctrl+p或者Ctrl+n | 在插入模式下,在你输入单词的开头字符后,通过Ctrl+p或者Ctrl+n快捷键可获得自动补全选项(自动补全数据基于所在文件生成) |
插入模式 | [插入]未探究 | [插入]未探究 | [插入]未探究 |
| gt | 跳转到右侧一个标签页 | 普通模式 | [普通]不支持 | [普通]未探究 | [普通]未探究 |
| gT | 跳转到左侧一个标签页 | 普通模式 | [普通]不支持 | [普通]未探究 | [普通]未探究 |
| :sp | 水平分割 | 命令模式 | [命令]未探究 | [命令]未探究 | [命令]未探究 |
| :vsp | 垂直分割 | 命令模式 | [命令]未探究 | [命令]未探究 | [命令]未探究 |
| :q | 在分屏环境中,退出当前分屏 | 命令模式 | [命令]未探究 | [命令]未探究 | [命令]未探究 |
| Ctrl+w h/l/k/j | 分别表示跳到左侧/右侧/上侧/下侧分屏 | 普通模式 | [普通]未探究 | [普通]未探究 | [普通]未探究 |
1.10、限定范围操作
1.10.1、“Range操作”形式
“Range”表示一个行范围,可以是单行。表示由“数字,特殊字符,书签,查找结果”元素构成。
示例如下。
| 行范围 | 描述 | 例子 |
|---|---|---|
| 21 | 行21 | :21s/old/new/g |
| 1 | 行1 | :1s/old/new/g |
| $ | 最后一行(注意,虽为同一个字符,上述体系中“$”表示最后一个字符,这里体系中“$”表示最后一行) | :$s/old/new/g |
| . | 当前行 | :.w single.txt(把当前行的内容写到文件“single.txt”) |
| % | 所有行,等价于“1,$” | :%s/old/new/g |
| 21,25 | 行21到行25 | :21,25s/old/new/g |
| 21,$ | 行21到最后一行 | :21,$s/old/new/g |
| .,$ | 当前行到最后一行 | :.,$s/old/new/g |
| .+1,$ | 当前行的下一行到最后一行 | :.+1,$s/old/new/g |
| .,.+5 | 当前行到第6行 | :.,.+5s/old/new/g |
| ‘<,’> | 选取行范围(本质上也是书签指定的行范围,详细可参见“2.1、模式”小节) | :'<,'>s/old/new/g |
| ‘a,’b | 书签a到书签b指定的行范围 | :'a,'bd |
| .,’b | 当前行到书签b指定的行范围 | :.,'bd |
| .,/BODY/ | 当前行到接下来第一次包含“BODY”的行范围 | .,/BODY/d |
1.10.2、“操作End”形式
“End”表示操作范围的一端,另外一端为当前光标所在位置。当“End”表示“行”范畴时,范围为“行到行”;当“End”表示“字符”范畴时,范围为“字符到字符”。
比如:
1 | y0:从行首开始复制(字符范畴) |
特别需要注意的是:
1、“ggguG”和“gggUG”逻辑上都分为两部分:gg和guG(gUG),而不是一个独立的整体从而被进一步误以为出现了“Start操作End”的限定范围操作形式
2、书签跳转语境中,“`a”是字符范畴,“’a”是行范畴
1.11、跳转操作
跳转行为包括:gg,G,NG,书签跳转等。
可通过:jumps查看跳转记录列表,小三角所指跳转记录表示当前所处跳转记录,如果小三角所指跳转记录为空行,表示还未有跳转记录。
Ctrl+o是跳转回退,相应的小三角往上移动,Ctrl+i是跳转前进,相应的小三角往下移动。
1.12、宏操作
录制宏:录制一系列动作,以备重复执行。
录制宏具体步骤如下:
1 | 按下q{0-9a-zA-Z"}开始录制,{0-9a-zA-Z"}为宏录制目的寄存器名字 |
通过@{0-9a-zA-Z"}执行指定宏,支持“重复执行N次操作”。
二、几个概念
2.1、模式
Vim编辑器提供多种模式,常见的模式有4种:普通模式,可视模式,插入模式,命令模式。
| 模式名称 | 描述 |
|---|---|
| 普通模式 | 日常模式 |
| 可视模式 | 主要用于选取内容供后续操作,选取完成后本质上是划定了一个限定范围 |
| 插入模式 | 主要用于插入数据 |
| 命令模式 | 主要用于执行命令 |
备注:
1、本质上,可视模式中选取时定义了两个特殊的书签,书签表示位置范围对应于选取限定范围,这两个特殊书签分别为:“<”和“>”,“<”对应于“限定范围开头”,“>”对应于“限定范围结尾”,因此'<和'>分别指向限定范围第一行和最后一行,`<和`>分别指向限定范围开头字符和结尾字符
2.2、重复执行N次操作
在操作前辅以一个表示数字的“N”,表示“重复执行N次操作”。需要注意的是,“NG”中的“N”并不是这个含义。
比如:
1 | 4h:执行4次h操作,即向左移动4个字符 |
五、常见需求实现
5.1、快速选中Java方法
快速选中Java方法步骤描述如下:
1、光标定位到方法定义首行,即具有方法名称的行
2、按下^字符,定位到所在行行首第一个非空字符
3、按下v字符,进入可视模式
4、按下/{<Enter>字符组合,查找到第一个“{”字符
5、按下%字符,查找到与上述“{”字符匹配的“}”字符,完成选中
根据上述描述,我们可在“.vimrc”配置文件中,通过如下语句配置快捷键“cm”:
1 | nmap cm ^v/{<CR>% |
5.2、Java源文件中快速定位到类名
Java源文件中快速定位到类名步骤描述如下:
1、按下gg,光标定位到文件首行
2、按下/^public<Enter>字符组合,查找到第一个“public”字符串,且该字符串位于行首
3、按下f{字符组合,找到右侧第一个“{”字符
4、按下?class\|interface\|enum<Enter>字符组合,向后找第一个“class/interface/enum”字符串
5、按下w字符,定位到右侧类名
根据上述描述,我们可在“.vimrc”配置文件中,通过如下语句配置快捷键“cc”:
1 | nmap cc gg/^public<CR>f{?class<Bslash><BAR>interface<Bslash><BAR>enum<CR>w |
5.3、去掉Windows文件中的^M符号
去掉Windows文件中的“^M”符号的命令如下:
1 | %s/^M//g |
如果想生成“^M”符号,可用Ctrl-v Ctrl-m命令。
5.4、剪切
进入可视模式后,选取内容,按下x或者d字符,然后在目的地按下p字符完成剪切,以上过程能够完成剪切的根本原因是:x和d操作在删除内容之前会在寄存器复制一份内容,p操作会从寄存器复制粘贴内容。
5.5、g命令
删除所有以“#”字符开头的行:
1 | :g/^#/d |
删除所有空行:
1 | :g/^$/d |
**参考文献:** [1]:help mark-motions [2]:help text-objects [3]:help q [4]:help jumps [5]:help various-motions [6]https://zh.wikipedia.org/wiki/Vim [7]http://vim.wikia.com/wiki/Ranges [8]http://www.cnblogs.com/abeen/archive/2010/07/28/1786594.html [9]https://www.maketecheasier.com/vim-keyboard-shortcuts-cheatsheet/ [10]https://www.fprintf.net/vimCheatSheet.html [11]https://gist.github.com/awidegreen/3854277 [12]https://coolshell.cn/articles/5426.html