Vim命令一学就会

361 阅读9分钟

vi/vim 命令大全

基本上 vi/vim 共分为三种模式

  • 普通命令模式(Command mode)
  • 输入模式/编辑模式/插入模式(Insert mode)
  • 底行命令模式(Last line mode)

这三种模式的作用分别是:

命令模式

启动 vi/vim后,默认进入命令模式。

该状态下键盘输入会被识别为命令,而不是编辑文本内容。比如按下i,并不会插入一个字符,而是被当作了一个命令。

以下是常用的几个命令:

  • i: 切换到输入模式,输入模式下就可以编辑文本内容。
  • x: 删除当前光标所在处的字符。
  • :: 英文冒号,切换到底线命令模式。

命令模式只有一些最基本的命令,因此仍要依靠底线命令模式输入更多命令。

输入模式/插入模式

在命令模式下按下i就进入了输入模式。

在输入模式中,可以使用以下按键:

  • 字符按键以及Shift组合: 输入字符
  • ENTER: 回车键,换行
  • BACK SPACE: 退格键,删除光标前一个字符
  • DEL: 删除键,删除光标后一个字符
  • 方向键: 在文本中移动光标
  • HOME/END: 移动光标到行首/行尾
  • Page Up/Page Down: 上/下翻页
  • Insert: 切换光标为输入/替换模式,光标将变成竖线/下划线
  • ESC: 退出输入模式,切换到命令模式

底线命令模式

在命令模式下按下:(英文冒号)就进入了底线命令模式。

底线命令模式可以输入单个或多个字符的命令,可用的命令非常多。

在底线命令模式中,基本的命令有(已省略前面的冒号)

  • q: 退出程序
  • w: 保存文件

按ESC键可随时退出底线命令模式。

简单的说,我们可以将这三个模式想成底下的图标来表示:

image.png

vi/vim 命令说明

除了上面简易范例的 i, Esc, :wq 之外,vim 还有非常多的按键可以使用。

命令模式基本语法

verb + noun # 动词 + 名词

这就类似与在英语中的祈使句:

"Eat(verb) a donut(noun)" "Kick(verb) a ball(noun)" "Learn(verb) the Vim Editor(noun)"

现在你需要的就是用Vim中基本的动词和名字来建立你的词汇表

名词(动作 Motion)

我们这里将 动作 Motion 作为名词, 动作Motion用来在Vim中到处移动。下面列出了一些常见的动作的例子:

h	 左
j	 下
k	 上
l	 右
w	 向前移动到下一个单词的开头
}	 跳转到下一个段落
$	 跳转到当前行的末尾

动词(操作符 Operator)

根据:h operator,Vim共有16个操作符,学习下面3个操作符在80%的情况下就已经够用了

y	 yank(复制)
d	 delete(删除)
c	 change 删除文本,将删除的文本存到寄存器中,进入插入模式

至于,为什么复制要叫yank, 针对这个问题可以看看这个问答: 为什么在 vi 的世界, 拷贝都使用 yank 这个词, 而不是 copy?

动词 和 名词 结合使用

现在知道了基本的动词和名词,就可以应用到命令中了

y$  复制当前位置到行尾的所有内容
dw  删除当前位置到下一个单词的开头
c}  修改当前位置到这个段落的结尾

动作 motions 也接受数字作为参数, 例如:

y2h  向左拷贝2个字符
d2w  删除后两个单词
c2j  修改后面两行

行级的 操作 operations (作用在整行中的操作符)在文本编辑中和其他的 操作符 一样,Vim允许你通过按两次 操作符使它执行行级的操作,例如dd,yy,cc来执行删除,复制或修改整个行。您可以使用其他operations试一下(比如gUgU)。

更多名词(文本对象 Text Objects)

文本通常是结构化的,特别是代码中,文本经常被放置在小括号、中括号、大括号、引号等当中。Vim提供了一种处理这种结构的文本对象的方法。

文本对象可以被 操作符 operations 使用,这里有两类文本对象:

  • i + object: 内部文本对象
  • a + object: 外部文本对象

内部文本对象选中的部分不包含包裹文本对象的空白或括号等,外部文本对象则包括了包裹内容的空白或括号等对象。外部对象总是比内部对象选中的内容更多。如果你的光标位于一对括号内部,例如console.log("hello world")中:

  • di( 删除括号内部的内容但保留括号, 结果 为 console.log()
  • da( 删除括号以及内部的内容, 结果 为 console.log

假设有这样一段js函数,你的光标停留在"Hello"中的"H"上:

function hello() {
  console.log("Hello world");
}

则对应的命令和结果

  • di( 删除整个"Hello world"
  • di{ 删除整个函数体内容, 结果 为 function hello() {}
  • diw 删除"Hello"这个单词

文本对象很强大, 你可以在同一个位置指向不同的内容,可以删除一对小括号中的文本,也可以是当前大括号中的函数体,也可以是当前单词。

下面列举一些常见的文本对象:

  • w 一个单词
  • p 一个段落
  • s 一个句子
  • () 一对()
  • {} 一对{}
  • [] 一对[]
  • <> 一对<>
  • t XML标签
  • " 一对""
  • ' 一对''
  • ` 一对``

你可以通过:h text-objects了解更多

接下来列出一些常用的vim命令及操作说明

第一部份:命令模式可用的光标移动、复制粘贴、搜索替换等

移动光标的方法

首先是 以字符为单位 的移动:

  • h 或 左箭头(←): 光标向左移动一个字符
  • j 或 下箭头(↓): 光标向下移动一个字符
  • k 或 上箭头(↑): 光标向上移动一个字符
  • l 或 右箭头(→): 光标向右移动一个字符
  • n<space>: n 表示「数字」;键入数字后再按空格键,光标会向右移动 n 个符。例如 10<space> 则光标会向右移动 10 个字符。

在字符之后,便是以文字为单元的移动:

  • W:移动到下一个单词的开头处
  • E:移动到下一个单词的结尾处
  • B:移动到前一个单词的开头处
  • gE:移动到前一个单词的结尾处

接下来是以「行」为单位的移动:

  • 0:移动到当前行的第一个字符处
  • ^:移动到当前行第一个非空字符处
  • g_:移动到当前行最后一个非空字符处
  • $:移动到当前行最后一个字符处
  • n|:移动到当前行的第n列
  • +: 光标移动到非空格符的下一行
  • -: 光标移动到非空格符的上一行
  • n<Enter>: n 表示「数字」。光标向下移动 n 行 (常用)

当然,用类似的Vim方式,还可以完成「段」级别、搜索、滚动、标记等一系列移动操作

  • Ctrl + f: 屏幕「向下」移动一页,相当于 [Page Down] 按键 (常用)
  • Ctrl + b: 屏幕「向上」移动一页,相当于 [Page Up] 按键 (常用)
  • Ctrl + d: 屏幕「向下」移动半页
  • Ctrl + u: 屏幕「向上」移动半页
  • H: 光标移动到当前屏幕最上方那一行的第一个字符
  • M: 光标移动到当前屏幕中间那一行的第一个字符
  • L: 光标移动到当前屏幕最下方那一行的第一个字符
  • G: 移动到整个文档的最后一行 (常用)
  • nG: n 表示「数字」;光标移动到当前文档的第 n 行。例如 10G 则会移动到文档的第 10 行 (可配合 :set nu 显示行号)
  • gg: 光标移动到文档的第一行,相当于 1G (常用)

如果想要进行多次移动的话,例如向下移动 30 行,可以使用 30j30↓ 的组合按键, 即键入操作的次数(数字)后,按下对应的操作键即可。

删除、复制与粘贴、大小写转化

  • x, X: 在一行字当中,x 为向后删除一个字符 (相当于 [del] 按键), X 为向前删除一个字符(相当于 [backspace] 亦即是退格键) (常用)

  • nx: n 表示「数字」。连续向后删除 n 个字符。举例来说,我要连续删除 10 个字符,则键入 10x

  • dd: 删除光标所在的一整行(常用)

  • ndd: n 表示「数字」。删除光标所在的向下 n 行,例如 10dd 则是删除 10 行 (常用)

  • d1G: 删除光标所在行到文档第一行的所有内容

  • dG: 删除光标所在行到文档最后一行的所有内容

  • d$: 删除光标位置到当前行最后一个字符之间的内容

  • d0: 删除光标位置到当前行第一个字符之间的内容

  • yy: 复制光标所在行的内容 (常用)

  • nyy: n 表示「数字」。复制光标所在行向下 n 行,例如 10yy 则是复制 10 行 (常用)

  • y1G: 复制光标所在行到文档第一行的所有内容

  • yG: 复制光标所在行到文档最后一行的所有内容

  • y0: 复制光标位置到当前行第一个字符之间的所有内容

  • y$: 复制光标位置到当前行最后一个字符之间的所有内容

  • p, P: p 将已复制的内容粘贴到光标下一行,P 则为粘贴到光标上一行!举例来说,我目前光标在第 10 行,且已经复制了一行内容。则按下 p 后, 会将复制的内容粘贴到第21行。如果是按下 P, 则会将复制的内容插入到第20行,原来第20行的内容会被挤到第21行 (常用)

  • J: 将光标所在行与下一行的内容合并成一行

  • c: 剪切内容并进入输入模式,比如,c0为剪切从光标位置到行首内容,并进入输入模式,c$为剪切从光标位置到行尾内容,并进入输入模式,

  • u: 撤销一步操作。相当于Ctrl + z (常用)

  • Ctrl + r: 重做上一个动作。(常用)

  • .: 小数点!表示重复前一个动作。 如果想要重复删除、重复粘贴等等,按下小数点「.」即可 (常用)

vim中大小写转化命令

  • gu:转化为小写
  • gU:转化为大写

例如:gUiw将单词转化为大写

搜索替换

  • /string: 从光标位置向后搜索 string 字符串。例如要在档案内搜寻 validate 这个字符串,就输入 /validate 即可 (常用)
  • ?string: 从光标位置向前搜索 string 字符串。
  • n: 这里的 n 是字母按键 n。代表重复前一个搜寻的动作。举例来说,如果我们执行了 /validate 去向后搜索 validate 这个字符串,则按下 n 后,会继续向后搜索下一个 validate 字符串。
  • N: 这里的 N 是字母按键 N。与 n 刚好相反,为「反向」搜索。

使用 /string 配合 n 及 N 可在关键词之前来回搜索

  • :n1,n2s/string1/string2/g: n1 与 n2 为数字。在 n1 与 n2 行范围内容搜索 string1 这个字符串,并将该字符串替换为 string2 ; 举例来说,要在 300 到 500 行之间搜索 validate 并替换为 validator 则键入 :300,500s/validate/validator/g。(常用)
  • :1,$s/string1/string2/g:%s/string1/string2/g: 从文档第一行到最后一行搜索 string1 字符串,并将该字符串替换为 string2 (常用)
  • :1,$s/string1/string2/gc:%s/string1/string2/gc: 从文档第一行到最后一行搜索 string1 字符串,并将该字符串替换为 string2,在替换之前提示字用户确认 (confirm) 是否需要替换 (常用)

第二部份:命令模式切换到编辑模式的命令说明

进入输入或替换的编辑模式

  • i, I 进入输入模式(Insert mode): i 为从光标所在位置开始输入, I 为从光标所在行的第一个非空格字符处开始输入。 (常用)
  • a, A 进入输入模式(Insert mode): a 为从光标下一个字符处开始输入, A 为从光标所在行的最后一个字符处开始输入。(常用)
  • o, O 进入输入模式(Insert mode): 英文字母 o 的大小写。o 为在光标所在行的下一行插入空行并开始输入; O 为在光标所在行的上一行插入空行并开始输入。(常用)
  • r, R 进入替换模式(Replace mode): r 替换光标位置的字符为新字符,只能替换一次;R 会从光标位置开始往后依次替换新字符,直到按下 ESC 为止;(常用)

上面这些按键中,在 vi 画面的左下角处会出现 --INSERT----REPLACE-- 的提示字样。 从提示名称就可以看出当前的操作

  • Esc 退出编辑模式,切换到普通的命令模式 (常用)

第三部份:命令模式切换到底线命令行模式可用的命令说明

保存、退出等指令

  • :w: 将编辑的内容写入文档 (常用)
  • :w!: 强制写入文档。
  • :q: 退出 vi 编辑器 (常用)
  • :q!: 不保存修改,强制退出。

注意,在 vi/vim 中,感叹号 ! 具有 强制 的意思

  • :wq: 保存并退出,若为 :wq! 则表示强制保存并退出 (常用)
  • :w [filename]: 将编辑的内容另存为一个新文件
  • :r [filename]: 读取另一个文件的内容并追加到光标所在行后面
  • :n1,n2 w [filename]: 将 n1 到 n2 行之间的内容保存到 filename 文件
  • :! command: 暂时离开 vi 界面,执行具体的bash命令并显示执行结果,按Enter键可再次回到 vi 界面。例如 :! ls /etc 即可在 vi 界面当中查看 /etc 目录内容。然后根据提示选择是否继续执行bash命令,或者按Enter键回到 vi 界面。

显示/隐藏 行号

  • :set nu: 显示行号,设置之后,会在每一行的前面显示对应的行号
  • :set nonu: 与 set nu 相反,取消显示行号

参考文章

Learn Vim (the Smart Way)