最近看了一本书Vim实用技巧,读完之后发现以前自己对vim只是略知皮毛,vim被称之为编辑器之神,就如一个巨大的宝矿,等待我们去挖掘,本文将简单介绍其中的一些技巧,希望对你有所帮助。
模式
常见的几种模式
- 普通模式
- 可视化模式
- 插入模式
- 命令模式
模式间转换
普通模式->插入模式:
- I:光标移到行首
- A:光标移到行尾
- O:向上插入一行空行,光标移至新行行首
- o:向下插入一行空行,光标移至新行行首
插入模式->普通模式:
<Esc>
或<Ctrl-[>
插入模式->插入-普通模式:<Ctrl-o>
插入-普通模式是普通模式的一个特例,在此模式中,我们可以执行一个普通模式命令,执行完后,马上就又返回到插入模式。
普通模式->可视化模式:
- v:以字符为单位选中区域
- V:以行为单位选中区域
- ctrl+v:以块为单位选中区域
- gv:用来重选上一次由可视模式所选择的文本范围
可视化模式<->选择模式->
在一个典型的文本编辑器环境中,当选中一段文本后,再输入任意可见字符时,这些选中的文本将会被删除。虽然 Vim 的可视模式未遵从此惯例,但是其选择模式(Select Mode)却按此方式工作。按
<Ctrl-g>
可以在可视模式及选择模式间切换。
移动
上下左右
除了最基本的通过上下左右箭头移动光标我们还可以通过h/j/k/l
按键代替箭头左下上右移动光标(具体对应关系可以想象下有两条反斜线\\
,最左边对应左移,最右边对应右移)。
移到行首/行尾
- 0:移到行首
- ^:移到当前行第一个可视化字符
- $:移到行尾(对应0)
- g_:移到当前行最后一个可视化字符(对应^)
实际行与屏幕行
与许多文本编辑器不同,Vim 会区分实际行与屏幕行。当 ‘wrap’ 设置被启用时(缺省启用),每个超出窗口宽度的文本行都会被回绕显示,以保证没有文本显示不出来。这样一来,文件中的一行也许会被显示为屏幕上的若干行。可以通过命令模式下执行:set nowrap隐藏超出屏幕的文本
wrap(默认):
nowrap:
在上面的h/j/k/l/0/^/$等操作前面加上g,则vim会根据屏幕行去做移动。
基于单词移动
- w/W:正向移动到下一单词的开头
- b/B:反向移动到当前单词/下一单词开头
- e/E:正向移动到当前单词/下一单词结尾
- ge/gE:反向移动到下一单词结尾
如图所示:
w和W:
- w(word):一个word包含一串字母、数字或下划线,或者一串非空字符,空行也被认为是一个word.
- W(WORD):一个WORD包含一串非空字符,空行也被认为是一个WORD,WORD的范围比word大
上面小写的命令对应word,大写的对应WORD
移到当前行指定字符
- 使用
f{char}
可以正向移动到当前行下一个char字符,F反向移动 ;
继续移动到下一个char字符(下一个的方向与f/F的方向一致),
回到上一个char字符- 使用
t{char}
可以正向移动到当前行的下一个char字符的前一个字符,T{char}
反向移动到上一个char字符的后一个字符,同样也可以使用;
和,
继续移动
移到某一行
- G:移到结尾行
- gg:移到首行
- nG:移到具体第n行,n为具体行数,例如10G移到第10行
:n<CR>
:在命令模式下,直接输入行号然后按回车也可以跳到第n行
翻页
- ctrl+f:下翻一页=>forward
- ctrl+d: 下翻半页=>down
- ctrl+b: 上翻一页(对应ctrl+f)=>back
- ctrl+u: 上翻半页(对应ctrl+d)=>up
还有个实用技巧,按zz
可以让当前光标所在行居中
设置位置标记以快速跳回
m{a-zA-Z}
命令会用选定的字母标记当前光标所在位置。'{mark}
命令跳到位置标记所在行,并把光标置于该行第一个非空白字符上- 而`{mark}命令则把光标移动到设置此位置标记时光标所在之处
例如:我们可以使用mm
标记当前光标所在位置,之后不管光标移到何处,只要使用`m即可跳回原来标记处
在匹配括号中跳转
% 命令允许我们在一组开、闭括号间跳转,可作用于()、{}以及[]
快速跳转到你最后一次编辑的地方并进入插入模式
gi
删除&替换
普通模式下
- x:删除单个字符
- s:删除光标所在字符并进入插入模式(substitute)
- daw(delete around word)删除单词(详见下文文本对象)
- dt{char}删除直到char字符
- d$删除到行尾
- d0删除到开头
- dd:删除当前行
- d/{string}:删除光标所在处到string之间的内容
- x跟d前面支持加数字
- cw/W:(change word/WORD)删除光标所在处到当前word/WORD的结尾,并进入插入模式
插入模式下
- ctrl+h:删除上一个字符
- ctrl+w:删除上一个单词
- ctrl+u:删除行首到光标所在处之间的字符
可视化模式下
选中区域后,按d删除该区域,按c删除并进入插入模式
以上这些操作也适用与unix命令行
复制粘贴
- y(yank):复制,例如进入可视化模式选中区域后按y可复制区域内容
- yy:复制一行
- {n}yy:复制n行
- p:把内容粘贴到光标之后
- P:把内容粘贴到光标之前
注意:使用d删除内容后紧跟着p/P操作,则粘贴的是删除的内容
查找替换
查找
- 使用
/
键执行一次查找时,Vim将在整个缓冲区内进行正向查找 - 用
?
键则会进行反向查找。 - 查找到目标后,使用
n
移动到下一个目标,N
移动到上一个目标
替换
普通模式下:
- r:替换单个字符
- R:替换多个字符
命令模式下:1
:[range]s[ubstitute]/{pattern}/{string}/{flags}
- range表示范围,比如10,20表示10-20行,%表示全部,空则表示当前行
- pattern是要替换的模式,可以是正则表达式,若为空,则表示使用上一次查找的模式
- string是替换后文本
Flags有几个常用的标志:
- g(global)表示全局范围内执行
- c(confirm)表示确认,可以确认或者拒绝修改
- n(number)报告匹配到的次数而不替换,可以用来查询匹配次数
文本对象
文本对象允许我们操作括号、被引用的文本、XML标签以及其他文本中的常见结构。文本对象由两个字符组成,第一个字符永远是 i 或是 a。我们一般说,以 i 开头的文本对象会选择分隔符内部的文本,而以 a 开头的文本对象则会选择包括分隔符在内的整个文本。为方便记忆,可以把i想成inner,a想成around
文本对象类型
w
:wordW
:WORDs
:sentencep
:paragraph]|[
:[] block)|(|b
: block>|<
: <> blockt
: tag block}|{|B
:Block- “|’|`: quoted string
用法:1
[number]<command>[text object or motion]
- number指命令作用在几个文本对象上
- command是指执行的具体命令,例如d(删除)/y(复制)/c(替换)
以删除为例:
- “dl”: delete character (alias: “x”)
- “diw”:delete inner word
- “daw”:delete a word
- “diW”:delete inner WORD (see |WORD|)
- “daW”:delete a WORD (see |WORD|)
- …以此类推
又如,以选中区域为例:
通过:h text-object
可查看文本对象帮助文档
映射
vim映射可以让用户根据自己的习惯自定义快捷键,使用:map命令可查看定义的全部映射
支持的前缀修饰符
- nore:no recursive表示非递归(默认是递归映射,即map a b;map b c;则按a键实际会执行c,使用非递归模式则只会执行b)
- n:表示在普通模式下生效(不加修饰符时默认为普通模式)
- v:表示在可视模式下生效
- i:表示在插入模式下生效
- c:表示在命令行模式下生效
例如:
:map - x
,然后按-可以删除字符:map <Ctrl-d> dd
使用ctrl+d代替dd:unmap -
可以删除-代表的映射:mapclear
清除所有map(包括用户定义和系统默认的键盘映射)inoremap ( ()<Left>
,插入模式下输入(时自动补全)并移到括号中间)
mapleader
可以使用特殊字符串<Leader>
去定义一个使用mapleader变量的映射,如果mapleader没有定义或者是空的,则默认使用反斜线\。例如:map <Leader>A o<Esc>
将会像:map \A o<Esc>
一样工作,但使用:let mapleader = ","
后,将像:map ,A o<Esc>
一样工作。
值得注意的是:
- mapleader的值只在定义时生效,对mapleader做的修改不会对已经定义的映射产生影响。
- 当按下
键时,默认情况下只有1000ms的时间去输入其后跟着的命令,可通过 timeoutlen
配置项修改
配置map
一般来说有两种方法配置map:
- 每次编辑时使用:map命令配置,单次编辑有效
- 将map命令配置到vimrc文件里,每次都生效
一般情况下应该使用非递归映射,防止与第三方插件配置冲突导致问题
寄存器
简介
Vim 的寄存器是一组用于保存文本的简单容器。它们既可像剪贴板那样,剪切、复制和粘贴文本;也可以记录一系列按键操作,把它们录制成宏。可以通过给命令加 “{register} 前缀的方式指定要用的寄存器。若不指明,Vim 将缺省使用无名寄存器。可通过:reg
查看所有寄存器内容,通过:reg {name}
查看指定寄存器的内容,
例如,通过"ayy
命令,可以把当前行复制到”a寄存器,然后通过"ap
,指定粘贴”a寄存器里面的内容
寄存器分类
寄存器可分为以下分类:
- 无名寄存器(“”):,不指定寄存器时默认使用
- 复制专用寄存器(“0):当我们使用 y{motion} 命令时,要复制的文本不仅会被拷贝到无名寄存器中,而且也被拷贝到了复制专用寄存器中,后者可用数字0加以引用。使用 x、s、c{motion} 以及 d{motion} 命令均不会覆盖该寄存器。
- 有名寄存器(“a-“z):用小写字母引用有名寄存器,会覆盖该寄存器的原有内容,而换用大写字母的话,则会将新内容添加到该寄存器的原有内容之后。
- 黑洞寄存器(“_):,有去无回,例如不会用到删除的内容则可以使用此寄存器,而不是默认覆盖无名寄存器
- 系统剪贴板(“+)与选择专用寄存器(“*)
- 表达式寄存器(“=)可以用来执行一段Vim脚本,并返回其结果
在插入模式中,输入
= 就可以访问这一寄存器。这条命令会在屏幕的下方显示一个提示符,我们可以在其后输入要执行的表达式。输入表达式后敲一下 ,Vim就会把执行的结果插入到文档的当前位置了。 - 其他寄存器
寄存器 | 内容 |
---|---|
“% | 当前文件名 |
“# | 轮换文件名 |
“. | 上次插入的文本 |
“: | 上次插入的Ex命令 |
“/ | 上次查找的模式 |
宏
宏可以看成一系列命令的集合,用来【录制】一系列操作,然后用于【回放】,适合针对一系列相似的行、段落,甚至是文件,进行重复性的修改。
我们以下面一段文本为例,我们想给每个链接加上双引号,可以用宏来实现1
2
3
4
5
6
7
8http://www.a.com
http://www.bb.com
http://www.ccc.com
http://www.dddd.com
http://www.eeeee.com
http://www.ffffff.com
http://www.ggggggg.com
http://www.e.com
录制宏
- 使用q来录制和结束录制
- 使用q{register}选择要保存的寄存器,把录制的命令保存其中
- 使用@{register}回放寄存器中保存的一系列命令
假如我们使用a寄存器来录制,先把光标移到首行,依次执行一以下命令:1
2
3
4
5
6
7
8qa
I"
<Esc>
$
a"
<Esc>
j
q
录制完可以使用:reg a查看寄存器内容。
需要注意的是录制宏的过程中需要兼容光标位置,如此例中光标不一定在行首,我们可以使用I让贯光标移到行首并插入
以串行方式执行宏
- 回放一次:@a
- 回放n次:n@a
值得注意的是,以串行方式执行宏,当动作命令失败时,宏将中止执行
以并行方式执行宏
先切换到可视化模式并选中要执行到区域,此处是从第二行到文件尾,因此我们可以使用VG,之后通过命令:normal @a
指示 Vim 在高亮选区中的每一行上执行这个宏,当其中某一行执行失败时,剩下的行也会继续执行
可视化模式下按:normal {cmd}表示像普通模式一样执行命令
其他技巧
加减数字
和 命令分别对数字执行加和减操作。在不带次数执行时,它们会逐个加减,但如果带一个次数前缀,那么就可以用它们加减任意整数。例如,如果我们把光标移到字符5上,执行 10 就会把它变成15。
转换大小写
- ~:单个字符大小写转换
- g~w:单词大小写转换
- gU/uw: 单词转换成大/小写(注意与上面不同的是无论单词里面的字符之前是大写还是小写最后都会转换为大/小写)
- g~$:光标所在处到行尾大小写转换
- gU/u$:光标所在处到行尾转成大写/小写
- g~~:当前行大小写转换(与光标位置无关)
*可视化模式下 U转成大写,u转成小写,~大小写转换
自动补全
Ctrl+n/p
:插入模式下唤起自动补全Ctrl+e
终止这次自动补全,其效果是下拉菜单将被清除,并恢复光标前的文本,即调用自动补全前所输入的内容。Ctrl+d
可以在命令模式自动补全
分屏
- :vs(垂直分屏)
- :sp(水平分屏)
+h/j/k/l切换
重复
.
重复上一次修改,[count].
重复count次- {n}yy/n{dd}等,表示复制/删除n行
其他有用命令
:e <path/to/file>
: 打开一个文件:saveas <path/to/file>
: 另存为 <path/to/file>:e!
:从磁盘中重新加载文件(撤销所有更改):set showcmd
:显示命令:!{cmd}
:调用外部命令,例如:!ls
可以查看当前文件夹的文件:ls
:列出所有被载入到内存中的缓冲区的列表:bn/p
:切换到下/上一个缓冲区(打开多个文件时有用)- 可视化模式下,
>
向右缩进,<
向左缩进,=
,o
变换可视化模式的光标端点
注意区分 :!ls 和 :ls 的不同之处。前者调用的是 shell 中的 ls 命令,而 :ls调用的是Vim的内置命令,用来显示缓冲区列表的内容