原文: How to Exit Vim – Vim Save and Quit Command Tutorial
从我开始编程的第一年起,我就一直在使用 Vim。不管使用什么 IDE/编辑器,Vim 插件总是我安装的第一个插件。
我知道,对于不熟悉 Vim 的人来说,使用 Vim 可能是一种挑战。在这篇文章中,我们将介绍一些基本的话题,比如如何退出(exit) Vim,而不是放弃(quit) Vim。
我还将介绍你可以用来使用相应帮助文档的命令。要做到这一点,首先我们需要按几次 ESC
键,然后运行所提供的命令,例如,:h vim-modes
,然后按 Enter
。
概述——如何退出 Vim
- 按一次 ESC 键(有时候是两次)
- 确保你使用的是英文输入法
- 下一步取决于当前的状态和你的期望:
- 如果你没有做任何改变,输入
:q
,然后按 Enter/return - 如果你做了一些改变,并希望保留它们,输入
:wq
并按 Enter/return - 如果你做了一些修改,并希望放弃它们,请输入
:q!
并按 Enter/return
如果你想更详细地了解它是如何工作的,让我们深入了解一下。
什么是 Vim 中的模式?
Vim 中有七种基础工作模式和另外七种被认为是基础模式的变种的模式。如果你想知道更多,你可以在 Vim 中运行 :h vim-modes
来阅读文档。
幸运的是,我们不需要知道所有这些模式就可以开始工作。但有三种模式是我们需要注意的:普通模式
(Normal Mode
)、插入模式
(Insert Mode
) 和 命令行模式
(Command-line Mode
)。
什么是 Vim 中的普通模式?
普通模式
是至关重要的,因为只有在 普通模式
下我们才能运行命令(也有例外,但这不在本文的讨论范围之内)。
比如,如果我们想阅读 vim-modes
的文档,那么我们必须首先确定我们是在 普通模式
下,然后再输入 :h vim-modes
。而进入 Normal Mode
最经典的方式就是按 ESC
键。即使你已经进入了 Normal Mode
,按 ESC
也会让你保持在 Normal Mode
,所以不用担心。
这个命令在文档中是这样的::h Normal
, :h mode-switching
。
什么是 Vim 中的插入模式?
你使用 插入模式
来编辑当前文件(在 Vim 中,这通常被称为 buffer
)。默认情况下,我们在打开一个文件后就处于 Normal Mode
。如果我们需要对当前文件进行修改,首先我们需要切换到 insert Mode
。
最常见的切换方式是在 Normal Mode
下,将光标导航到我们要编辑的地方后按 i
键。
其实也有很多其他的方法可以进入 Insert Mode
,比如 o
、O
、a
、A
、I
等等。
这个命令在文档中是这样的::h Insert
, :h i_<Esc>
, :h o
, :h O
, :h a
, :h A
, :h I
。
什么是 Vim 中的命令行模式?
命令行模式
通常是一种“短期”模式,你使用它来运行 “Ex 命令”(不要与普通模式
中的“命令”混淆)。
有趣的事实:Vim 实际上是 Vi Improved
的缩写,它基于另一个名为 vi
的文本编辑器。vi
基于一个名为 ex
的行编辑器。vi
和 ex
都是由 Bill Joy 开发的。
对于 macOS 用户来说,另一个有趣的事实是:macOS 上只有 Vim
,命令 vi
是 Vim
的符号链接(symlink)。需要注意的是,命令行模式
下的 “Ex command” 与普通模式
下的 “command” 是不同的。
你可以在普通模式
下输入 :
进入命令行模式
。例如,如果你运行上面的命令来查看文档,只要你输入 :
,那么你实际上是在使用命令行模式
。
同样,如果你想切换回正常模式
,按 ESC
。
这个命令在文档中是这样的::h Command-line
、:h cmdline-lines
。
如何退出 Vim
如果你查看一下 :h quit
的文档,会注意到 quit
的前缀是 :
。这意味着 quit
是在命令行模式
中使用的。
为了进入命令行模式
,首先我们需要确保处于普通模式
,然后只需输入 :
。现在我们进入了命令行模式
,只需输入 quit
并按 Enter
或 return
。
你可能还会注意到 :q
,它实际上是 :quit
命令的简写版本。也就是说,我们也可以通过执行 :q
来退出 Vim。
不过,它提到,“当做出更改且 Vim 拒绝放弃当前 buffer”时,该命令将失败(如果你还记得,buffer 只是打开的文件,没什么特别的)。
在这种情况下,我们需要使用 :wq
,这意味着“写入并退出”。你可以在文档 :h:wq
下找到它。
:x
是另一个与 :wq
几乎相同的命令。根据 :h:x
,它是“类似于 :wq
,但只在做出更改时写入”。
这里的区别在于,无论你是否对其进行了更改,:wq
将保存文件。如果你没有做任何更改,:x
将不会保存文件。这里重要的是文件的修改时间,因为 :wq
会更新修改时间,而 :x
不会。
有些时候,我们宁愿不保留我们所做的更改。此时,我们需要 :q!
命令。!
通常被称为 “bang”,这使得 q!
就像是“强制退出”。
请注意,如果使用这种方式,你将丢失对该文件所做的所有更改,而且几乎没有办法恢复它们。
如何解决退出 Vim 的问题
如果我不想进入命令行模式怎么办?
没问题。在 Normal Mode
下,你也可以按 ZZ
或 ZQ
来退出 Vim。其中 ZZ
与 :x
相同,ZQ
与 :q!
相同。
在这里,ZZ
和 ZQ
被认为是 Normal Mode
的命令,而 :x
和 :q!
是 Ex 命令。
如果 :wq 失败了怎么办?
这是可能的,因为当文件是只读的或者文件名丢失时,:wq
可能会失败。
请注意,当一个文件是只读的,Vim 不会阻止你打开和编辑该文件。你可能也会发现 :wq!
在那个时候也不能工作。你可能最终会放弃所有用 :q!
进行的修改,然后打开同一文件,以 sudo
为前缀,再做一次同样的修改。
你可以做的一件事是把这个文件保存在另一个你有写权限的目录下,比如 ~
或者甚至是 /tmp
,然后把它移回你没有写入权限的目录。
为了实现这一点,你可以运行 :w ~/my-backup-file
,这将把该文件保存在 ~
下
接下来,你可以使用 mv
命令移动这个文件。还要注意,当 Vim 抱怨文件名丢失时,你需要这样做。
Vim 内部还有另一个解决方案。你可以运行以下命令::w !sudo tee %
。!sudo
表示在 shell 环境中运行 sudo 命令。
例如,:ls
将列出 Vim 中的所有缓冲区,但是 :!ls
将从 shell 运行 ls
命令并显示结果。tee
从标准输入(又名 stdin
)复制到标准输出(又名 stdout
)。%
为当前文件名。
这意味着我们从 shell 环境中使用 sudo
命令,从 Vim 复制当前文件(注意:修改过的版本)的内容,并将修改过的内容重定向到文件(通过使用文件名引用)。
你会注意到上面的警告。发生此警告是因为在 shell 环境中更新了文件内容而没有引起 Vim 的注意。所以 Vim 认为这是一个外部变化,并让你知道发生了什么。
此时只需按 Enter
,因为你是有意进行外部更改的。
你可能还会注意到,修改后的文件内容也显示在警告消息的上方。这是意料之中的,因为它来自标准输出 stdout
。如果你不想看到它,你可以执行 :w !sudo tee% >/dev/null
,这将丢弃来自 tee
的 stdout
。
如果我需要强制退出怎么办?
如果我们尝试按 control + c
退出,Vim 会显示上述信息。但你仍然可以通过在 Windows 上按 Ctrl + Alt + Delete
或者在 macOS 上按 Force Quit...
来解决这个问题。
下一次,当你试图再次打开同一个文件时,你应该看到这个(这里我用一个名为 foo.txt
的文件作为例子)。
不要惊慌——这是预料之中的事,因为 Vim 正试图帮助你恢复你可能丢失的宝贵修改。
通过检查该目录,你会发现一个扩展名为 .swp
的文件。这是一个 swap
文件(文档::h swap-file
)。
如果我们按 R
键恢复,我们将看到以下情况:
按 Enter
键后,现在你会发现你之前所做的修改又回来了。在你完成恢复过程后,你可以简单地删除 .swp
文件,这样你就不会再看到上面的错误。
总结
在这篇文章中,我们介绍了一些关于 Vim 模式的基本知识以及如何退出 Vim。我们还学习了如何解决退出 Vim 时的常见问题。
谢谢你阅读本文。谈到 Vim,还有很多东西需要学习。但如果你想了解更多,请随时探索 Vim 的帮助文档。