有一个老笑话说,一位来纽约市的游客向路人问路,告诉他去这座城市著名的古典音乐场所的路: 参观者:打扰一下,我怎么去卡内基音乐厅? 路人:练习,练习,练习!practice
学习Linux命令行,就像成为一名有成就的钢琴家一样,不是我们一下午就能学会的。这需要多年的实践。在本章中,我们将介绍 vi
(发音为“vee eye”)文本编辑器,它是Unix传统中的核心程序之一。vi
以其独特的用户界面而臭名昭著(notorious),但当我们看到一位大师坐在键盘前开始“演奏”时,我们确实会见证一些伟大的艺术。在本章中,我们不会成为大师,但等我们完成了,我们就会知道如何在 vi
中演奏“筷子”(chopsticks)。
第十二章:浅谈vi(m)为什么要学习 vi
小背景启动和停止 vi
兼容模式编辑模式进入插入模式保存我们的工作四处移动光标基本编辑追加文本新开一行删除文本剪切、复制、粘贴文本连接行查找和替换在行内搜索搜索整个文件全局搜索和替换编辑多个文件在文件之间切换打开其他文件进行编辑将内容从一个文件复制到另一个文件将整个文件插入到另一个文件中保存我们的工作Bash也支持vi总结
vi
在这个图形编辑器和易于使用的基于文本的编辑器(如 nano
)的现代时代,我们为什么要学习 vi
?有三个很好的理由。
vi
几乎总是可用的。
如果我们有一个没有图形界面的系统,比如远程服务器或GUI配置损坏的本地系统,这可能是一个救星。 nano
虽然越来越受欢迎,但仍然没有普及。POSIX是Unix系统上程序兼容性的标准,要求 vi
存在。
vi
是轻量级和快速的。
对于许多任务,打开 vi
比在菜单中找到图形文本编辑器并等待其多兆字节加载更容易。此外, vi
是为打字速度而设计的。正如我们将看到的,一个熟练的 vi
用户在编辑时永远不必从键盘上抬起手指。
我们不希望其他Linux和Unix用户认为我们是懦夫。
好吧,也许有两个很好的理由。
vi
的第一个版本是由加州大学伯克利分校的学生比尔·乔伊于1976年编写的,他后来与人共同创立了Sun微系统公司。vi
的名字来源于“visual(视觉)”一词,因为它旨在允许在带有移动光标的视频终端上进行编辑。在视觉编辑器(visual editors)出现之前,有一种行编辑器(line editors)一次只处理一行文本。要指定更改,我们告诉行编辑器转到特定行并描述要进行的更改,例如添加或删除文本。随着视频终端(而不是电传打字机等基于打印机的终端)的出现,视觉编辑成为可能。 vi
实际上包含了一个名为 ex
的强大的行编辑器,我们可以在使用 vi
时使用行编辑命令。
大多数Linux发行版不包含真正的 vi
;相反,它们附带了Bram Moolenaar编写的名为 vim
(“vi improved”,vi改善,的缩写)的增强替代品。vim
是对传统Unix vi
的实质性改进,在Linux系统上通常与 vi
这个名字有象征性的联系(或别名)。在接下来的讨论中,我们将假设我们有一个名为 vi
的程序,它实际上是 vim
。
vi
要启动 vi
,只需要简单键入以下:
xxxxxxxxxx
[me@linuxbox ~]$ vi
应该出现这样的屏幕:
xxxxxxxxxx
~
~
~ VIM - Vi Improved
~
~ version 8.0.707
~ by Bram Moolenaar et al.
~ Vim is open source and freely distributable
~
~ Sponsor Vim development!
~ type :help sponsor<Enter> for information
~
~ type :q<Enter> to exit
~ type :help<Enter> or <F1> for on-line help
~ type :help version8<Enter> for version info
~
~ Running in Vi compatible mode
~ type :set nocp<Enter> for Vim defaults
~ type :help cp-default<Enter> for info on this
~
~
~
正如我们之前对nano所做的那样,首先要学习的是如何退出。要退出,我们输入以下命令(注意冒号字符是命令的一部分):
xxxxxxxxxx
:q
shell提示符应该返回。如果由于某种原因,vi
无法退出(通常是因为我们对尚未保存的文件进行了更改),我们可以通过在命令中添加感叹号来告诉 vi
我们是认真的。
xxxxxxxxxx
:q!
提示:如果您在 vi
中“迷路”,请尝试按 Esc 键两次以重新找到方向。
在上面的示例启动屏幕中,我们看到文本 Running in Vi compatible mode(在Vi兼容模式下运行)。这意味着 vim
将在更接近 vi
正常行为的模式下运行,而不是 vim
的增强行为。为了本章的目的,我们希望以增强的行为运行 vim
。要做到这一点,你有几个选择。尝试运行 vim
而不是 vi
。如果可行,请考虑在 .bashrc 文件中添加 alias vi='vim'
。或者,使用此命令向 vim
配置文件添加一行:
xxxxxxxxxx
echo "set nocp" >> ~/.vimrc
不同的Linux发行版以不同的方式打包 vim
。一些发行版默认安装了 vim
的最小版本(即 vim-tiny
),该版本仅支持有限的 vim
功能集。在执行以下课程时,您可能会遇到缺少的功能。如果是这样,请安装 vim
的完整版本。
让我们再次启动vi,这次将一个不存在的文件的名称传递给它。这就是我们如何使用 vi
创建一个新文件:
xxxxxxxxxx
[me@linuxbox ~]$ rm -f foo.txt
[me@linuxbox ~]$ vi foo.txt
如果一切顺利,我们应该得到这样的屏幕:
xxxxxxxxxx
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
"foo.txt" [New File]
前导波浪号字符(~)表示该行上不存在文本。这表明我们有一个空文件。先别打字!
学习 vi
的第二件最重要的事情(在学习如何退出之后)是 vi
是一个模态编辑器(modal editor)。当 vi
启动时,它以正常模式(normal mode)启动。在这种模式下,几乎每个键都是一个命令,所以如果我们开始打字, vi
基本上会发疯,弄得一团糟。
要在文件中添加一些文本,我们必须首先进入插入模式(insert mode)。为此,我们按 i 键。之后,如果 vim
在其通常的增强模式下运行,我们应该在屏幕底部看到以下内容(这在vi兼容模式下不会出现):
xxxxxxxxxx
-- INSERT --
现在我们可以输入一些文本。试试这个:
xxxxxxxxxx
The quick brown fox jumps over the lazy dog.
要退出插入模式并返回正常模式,请按 Esc 键。
为了保存我们刚刚对文件所做的更改,我们必须进入命令模式(command mode)。在正常模式下按 : 键即可完成此操作。执行此操作后,冒号字符应出现在屏幕底部。
xxxxxxxxxx
:
要写入修改后的文件,我们在冒号后加上 w ,然后按 Enter 键。
xxxxxxxxxx
:w
文件将被写入硬盘,我们应该在屏幕底部收到一条确认消息,如下所示:
xxxxxxxxxx
"foo.txt" [New] 1L, 45C written
注意: vim
调用三种主要的编辑模式,normal(正常)、insert(插入)和 command(命令)。真正的 vi
(及其文档)分别称这些模式为: command 、insert 和 ex 。许多在线 vi
资料都会这样引用它们,是的,这可能会令人困惑。
在正常模式下,vi
提供了大量的移动命令,其中一些命令与 less
命令共享。下表列出了一个子集。
按键 | 移动光标 |
---|---|
l 或 → | 向右一个字符 |
h 或 ← | 向左一个字符 |
j 或 ↓ | 向下一行 |
k 或 ↑ | 向上一行 |
0 | 到当前行首 |
^ | 到当前行的第一个非空白字符。 |
$ | 到当前行尾 |
w | 到下一个单词或标点符号的开头。 |
W | 到下一个单词的开头,忽略标点符号。 |
b | 到前一个单词或标点符号的开头。 |
B | 到前一个单词的开头,忽略标点符号。 |
Ctrl - f 或 PageDown | 向下一页 |
Ctrl - b 或 PageUP | 向上一页 |
numberG | 到第 number 行。例如,1G 表示移动到文件的第一行 |
G | 到文件的最后一行 |
A | 到行尾,并进入追加模式,相当于 $a |
为什么 h、j、k 和 l 键用于光标移动?最初编写 vi
时,并非所有视频终端都有箭头键,熟练的打字员可以使用常规键盘键移动光标,而无需将手指从键盘上抬起。
vi
中的许多命令都可以用数字作为前缀,就像上面列出的 G
命令一样。通过在命令前加上数字,我们可以指定执行命令的次数。例如,命令 5j 使 vi
将光标向下移动五行。
大多数编辑包括一些基本操作,如插入文本、删除文本以及通过剪切和粘贴移动文本。当然, vi
以其独特的方式支持所有这些操作。vi
还提供了一种有限形式的撤消。如果我们在正常模式下按 u 键,vi
将撤消您上次所做的更改。当我们尝试一些基本的编辑命令时,这将派上用场。
【关于 u ,可能会有无法预期的效果,不建议多用】
append —— 追加
vi
有几种不同的方式进入插入模式。我们已经使用 i
命令插入文本。
让我们暂时回到 foo.txt 文件:
xxxxxxxxxx
The quick brown fox jumps over the lazy dog.
如果我们想在这句话的末尾添加一些文本,我们会发现 i
命令不会这样做,因为我们不能将光标移动到行尾之外。vi
提供了一个追加文本的命令,这个命令的名称很合理。如果我们将光标移动到行尾并键入 a ,光标将移动到行尾,vi
将进入插入模式。这将使我们能够添加更多文本。
xxxxxxxxxx
The quick brown fox jumps over the lazy dog. It was cool.
记得按 Esc 键退出插入模式。
由于我们几乎总是想将文本附加到行的末尾,vi
提供了一个快捷方式,可以移动到当前行的末尾并开始附加。这是 A 命令。让我们尝试一下,并在文件中添加更多行。
首先,我们将使用 0(零)命令将光标移动到行首。现在我们键入 A 并添加以下文本行:
xxxxxxxxxx
The quick brown fox jumps over the lazy dog. It was cool.
Line 2
Line 3
Line 4
Line 5
再次按 Esc 键退出插入模式。
正如我们所看到的,A 命令更有用,因为它在开始插入模式之前将光标移动到行尾。
我们插入文本的另一种方式是“打开”一行。这将在两个现有行之间插入一个空行,并进入插入模式。如下表所示,这有两种变体。
命令 | 打开 |
---|---|
o | 在当前行下面新开一行 |
O | 在当前行上面新开一行 |
我们可以这样演示:将光标放在“Line 3”上,然后键入 o :
xxxxxxxxxx
The quick brown fox jumps over the lazy dog. It was cool.
Line 2
Line 3
Line 4
Line 5
在第三行下方打开了一个新行,并进入了插入模式。按 Esc 键退出插入模式。按 u 键撤消我们的更改。
按 O 键打开光标上方的行:
xxxxxxxxxx
The quick brown fox jumps over the lazy dog. It was cool.
Line 2
Line 3
Line 4
Line 5
按 Esc 键退出插入模式,按 u 撤消更改。
正如我们所料, vi
提供了多种删除文本的方法,所有这些方法都包含两个按键中的一个。首先, x
命令将删除光标位置处的字符。x
前面可以有一个数字,指定要删除的字符数。d
命令更通用。与 x
一样,它前面可以有一个数字,指定要执行删除的次数。此外,d
后面总是跟着一个控制删除大小的移动命令。下表提供了一些示例:
命令 | 删除 |
---|---|
x | 当前字符 |
3x | 当前字符和接下来的两个字符 |
dd | 当前行 |
5dd | 当前行和接下来的四行 |
dw | 从当前光标位置到下一个单词的开头 |
d$ | 从当前光标位置到当前行的末尾 |
d0 | 从当前光标位置到行首 |
d^ | 从当前光标位置到行中的第一个非空白字符 |
dG | 从当前行到文件末尾 |
d20G | 从文件的当前行到第二十行 |
将光标放在文本第一行的单词 It
上。反复按 x 键,直到句子的其余部分被删除。接下来,反复按 u 键,直到删除操作撤消。
注意:真 vi
只支持单级撤消。 vim
支持多级撤销。
让我们再次尝试删除,这次使用 d
命令。再次将光标移动到单词 It
,然后键入 dW
删除该单词:
xxxxxxxxxx
The quick brown fox jumps over the lazy dog. was cool.
Line 2
Line 3
Line 4
Line 5
键入 d$
从光标位置删除到行尾:
xxxxxxxxxx
The quick brown fox jumps over the lazy dog.
Line 2
Line 3
Line 4
Line 5
按 dG
键从当前行删除到文件末尾。
xxxxxxxxxx
~
~
~
~
~
按三次 u
可撤消删除。
d
命令不仅删除文本,还“剪切(cuts)”文本。每次我们使用 d
命令时,删除内容都会被复制到粘贴缓冲区(比如剪贴板)中,稍后我们可以用 p
命令将缓冲区的内容粘贴到光标后,或者用 P
命令将内容粘贴在光标前。
y
命令用于“yank”(复制)文本,与 d
命令用于剪切文本的方式大致相同。下表提供了将y
命令与各种移动命令组合的一些示例:
命令 | 复制 |
---|---|
yy | 当前行 |
5yy | 当前行和接下来四行 |
yw | 从当前光标位置到下一个单词开始 |
y$ | 从当前光标位置到当前行尾 |
y0 | 从当前光标位置到行首 |
y^ | 从当前光标位置到行中的第一个非空白字符 |
yG | 从当前行到文件末尾 |
y20G | 从当前行到第二十行 |
让我们试试复制粘贴。将光标放在文本的第一行,然后键入 yy
以复制当前行。接下来,将光标移动到最后一行(G
),然后键入 p
将该行粘贴到当前行下方。
xxxxxxxxxx
The quick brown fox jumps over the lazy dog. It was cool.
Line 2
Line 3
Line 4
Line 5
The quick brown fox jumps over the lazy dog. It was cool.
和以前一样, u
命令将撤消我们的更改。光标仍位于文件的最后一行,键入 P
将文本粘贴到当前行上方。
xxxxxxxxxx
The quick brown fox jumps over the lazy dog. It was cool.
Line 2
Line 3
Line 4
The quick brown fox jumps over the lazy dog. It was cool.
Line 5
尝试上表中的其他 y
命令,了解 p
和 P
命令的行为。完成后,将文件恢复到原始状态。
vi
对行(line)的概念相当严格。通常,不可能将光标移动到行尾并删除行尾字符以将一行与其下一行连接起来【vi
不能处理换行符?】。因此,vi
提供了一个特定的命令 J
(不要与用于光标移动的 j
混淆)来将行连接在一起。
如果我们将光标放在 Line 3
行并键入 J
命令,会发生以下情况:
xxxxxxxxxx
The quick brown fox jumps over the lazy dog. It was cool.
Line 2
Line 3 Line 4
Line 5
vi
能够根据搜索将光标移动到各个位置。它可以在单行或整个文件上执行此操作。它还可以在用户确认或不确认的情况下执行文本替换。
f
命令搜索一行并将光标移动到指定字符的下一个实例。例如,命令 fa
将光标移动到当前行中字符 a
的下一个位置。在一行内执行字符搜索后,可以通过键入分号(;
)重复搜索。
要将光标移动到单词或短语的下一个位置,可以使用 /
命令。这与我们之前在 less
程序中了解到的方式相同。当您键入 /
命令时,屏幕底部将显示 /
。接下来,键入要搜索的单词或短语,然后按 Enter 键。光标将移动到包含搜索字符串的下一个位置。可以使用 n
命令重复搜索。这里有一个例子:
xxxxxxxxxx
The quick brown fox jumps over the lazy dog. It was cool.
Line 2
Line 3
Line 4
Line 5
将光标放在文件的第一行。键入以下内容,然后按 Enter 键。
xxxxxxxxxx
/Line
光标将移动到第2行。接下来,键入 n
,光标将移动到第3行。重复 n
命令将使光标在文件中向下移动,直到它用完匹配项。虽然到目前为止,我们的搜索模式只使用了单词和短语,但 vi
允许使用正则表达式(regular expressions),这是一种表达复杂文本模式的强大方法。我们将在【第19章.正则表达式】中全面介绍正则表达式
vi
使用命令模式对一系列行或整个文件执行搜索和替换操作(在 vi
中称为 substitution ,替换)。要将整个文件的单词“Line”更改为“line”,我们将输入以下命令:
xxxxxxxxxx
:%s/Line/line/g
让我们把这个命令分解成单独的项目,看看每个项目的作用:
项目 | 含义 |
---|---|
: | 冒号字符进入命令模式。 |
% | 这指定了操作的行范围。% 是从第一行到最后一行的快捷方式。或者,该范围可以指定为 1,5 (因为我们的文件有五行长)或 1,$ ,这意味着“从第1行到文件中的最后一行”。如果省略了行范围,则仅在当前行上执行操作。 |
s | 这指定了操作。在这种情况下,它是替换(substitution,搜索和替换)。 |
/Line/line/ | 这指定了搜索范式(pattern)和替换文本。 |
g | 这意味着“global(全局)”,即对行中搜索字符串的每个实例执行搜索和替换。如果省略,则仅替换每行上搜索字符串的第一个实例。 |
执行搜索和替换命令后,我们的文件看起来像这样:
xxxxxxxxxx
The quick brown fox jumps over the lazy dog. It was cool.
line 2
line 3
line 4
line 5
我们还可以指定一个带有用户确认的替换命令。这是通过在命令末尾添加一个 c
来实现的。这里有一个例子:
xxxxxxxxxx
:%s/line/Line/gc
此命令将把我们的文件更改回以前的形式;然而,在每次替换之前, vi
都会停止并要求我们用以下消息确认替换:
xxxxxxxxxx
replace with Line (y/n/a/q/l/^E/^Y)?
括号内的每个字符都是可能的选择,如下表所示:
关键字 | 动作 |
---|---|
y | 执行替换。 |
n | 跳过此模式实例。 |
a | 对该模式的此实例和所有后续实例执行替换。 |
q 或 Esc | 退出替换。 |
l | 执行此替换,然后退出。这是“last”的缩写。 |
Ctrl - e ,Ctrl - y | 分别向下和向上滚动。这对于查看拟议替代(proposed substitution)的上下文非常有用。 |
如果键入 y
,将执行替换; n
将使 vi
跳过此实例并继续下一个实例。
一次编辑多个文件通常很有用。您可能需要更改多个文件,或者可能需要将内容从一个文件复制到另一个文件。使用 vi
,我们可以通过在命令行上指定多个文件来打开它们进行编辑。
vi file1 file2 file3 ...
让我们退出现有的 vi
会话并创建一个新文件进行编辑。键入:wq
退出 vi
,保存修改后的文本。接下来,我们将在主目录中创建一个可供测试的附加文件。我们将通过捕获 ls
命令的一些输出来创建文件:
xxxxxxxxxx
[me@linuxbox ~]$ ls -l /usr/bin > ls-output.txt
让我们用 vi
编辑我们的旧文件和新文件。
xxxxxxxxxx
[me@linuxbox ~]$ vi foo.txt ls-output.txt
vi
将启动,我们将在屏幕上看到第一个文件:
xxxxxxxxxx
The quick brown fox jumps over the lazy dog. It was cool.
Line 2
Line 3
Line 4
Line 5
要从一个文件切换到下一个文件,请使用以下ex命令:
xxxxxxxxxx
:bn
要移回上一个文件,请使用以下操作:
xxxxxxxxxx
:bp
虽然我们可以从一个文件移动到另一个文件,但 vi
强制执行一项策略,如果当前文件有未保存的更改,则阻止我们切换文件。要强制 vi
切换文件并放弃更改,请在命令中添加感叹号(!
)。
除了上述切换方法外, vim
(和 vi
的一些版本)还提供了一些命令模式命令,使多个文件更容易管理。我们可以使用 :buffers
命令查看正在编辑的文件列表。这样做将在显示器底部显示文件列表:
xxxxxxxxxx
:buffers
1 %a "foo.txt" line 1
2 "ls-output.txt" line 0
Press ENTER or type command to continue
要切换到另一个缓冲区(文件),请键入 :buffer
,后跟要编辑的缓冲区编号。例如,要从包含 foo.txt 文件的缓冲区1切换到包含 ls-output.txt 文件的缓冲区2,我们可以键入以下命令:
xxxxxxxxxx
:buffer 2
我们的屏幕现在显示第二个文件。另一种更改缓冲区的方法是使用前面提到的 :bn
(buffer next的缩写)和 :bp
(buffer previous的缩写)命令。
也可以将文件添加到我们当前的编辑会话中。命令模式命令 :e
(“edit”的缩写)后跟一个文件名将打开一个附加文件。让我们结束当前的编辑会话并返回命令行。
用一个文件重新启动 vi
:
xxxxxxxxxx
[me@linuxbox ~]$ vi foo.txt
要添加第二个文件,请输入以下内容:
xxxxxxxxxx
:e ls-output.txt
它应该出现在屏幕上。第一个文件仍然存在,我们可以验证:
xxxxxxxxxx
:buffers
1 # "foo.txt" line 1
2 %a "ls-output.txt" line 0
Press ENTER or type command to continue
在编辑多个文件时,我们经常希望将一个文件的一部分复制到正在编辑的另一个文件中。使用我们之前使用的常用yank和paste命令很容易做到这一点。我们可以证明如下。首先,使用我们的两个文件,通过输入以下命令切换到缓冲区1(foo.txt):
xxxxxxxxxx
:buffer 1
这应该给我们以下信息:
xxxxxxxxxx
The quick brown fox jumps over the lazy dog. It was cool.
Line 2
Line 3
Line 4
Line 5
接下来,将光标移动到第一行,然后键入 yy
以拖动(复制)该行。
通过输入以下内容切换到第二个缓冲区:
xxxxxxxxxx
:buffer 2
屏幕现在将包含一些这样的文件列表(此处仅显示一部分):
xxxxxxxxxx
total 343700
-rwxr-xr-x 1 root root 31316 2017-12-05 08:58 [
-rwxr-xr-x 1 root root 8240 2017-12-09 13:39 411toppm
-rwxr-xr-x 1 root root 111276 2018-01-31 13:36 a2p
-rwxr-xr-x 1 root root 25368 2016-10-06 20:16 a52dec
-rwxr-xr-x 1 root root 11532 2017-05-04 17:43 aafire
-rwxr-xr-x 1 root root 7292 2017-05-04 17:43 aainfo
将光标移动到第一行,然后通过键入 p
命令粘贴我们从前一个文件复制的行:
xxxxxxxxxx
total 343700
The quick brown fox jumps over the lazy dog. It was cool.
-rwxr-xr-x 1 root root 31316 2017-12-05 08:58 [
-rwxr-xr-x 1 root root 8240 2017-12-09 13:39 411toppm
-rwxr-xr-x 1 root root 111276 2018-01-31 13:36 a2p
-rwxr-xr-x 1 root root 25368 2016-10-06 20:16 a52dec
-rwxr-xr-x 1 root root 11532 2017-05-04 17:43 aafire
-rwxr-xr-x 1 root root 7292 2017-05-04 17:43 aainfo
也可以将整个文件插入到我们正在编辑的文件中。为了看到这一点,让我们结束 vi
会话,只使用一个文件开始一个新的会话。
xxxxxxxxxx
[me@linuxbox ~]$ vi ls-output.txt
我们将再次看到我们的文件列表:
xxxxxxxxxx
total 343700
-rwxr-xr-x 1 root root 31316 2017-12-05 08:58 [
-rwxr-xr-x 1 root root 8240 2017-12-09 13:39 411toppm
-rwxr-xr-x 1 root root 111276 2018-01-31 13:36 a2p
-rwxr-xr-x 1 root root 25368 2016-10-06 20:16 a52dec
-rwxr-xr-x 1 root root 11532 2017-05-04 17:43 aafire
-rwxr-xr-x 1 root root 7292 2017-05-04 17:43 aainfo
将光标移动到第三行,然后输入以下命令模式命令:
xxxxxxxxxx
:r foo.txt
:r
命令(“read”的缩写)在光标位置下方插入指定的文件。我们的屏幕现在应该是这样的:
xxxxxxxxxx
total 343700
-rwxr-xr-x 1 root root 31316 2017-12-05 08:58 [
-rwxr-xr-x 1 root root 8240 2017-12-09 13:39 411toppm
The quick brown fox jumps over the lazy dog. It was cool.
Line 2
Line 3
Line 4
Line 5
-rwxr-xr-x 1 root root 111276 2018-01-31 13:36 a2p
-rwxr-xr-x 1 root root 25368 2016-10-06 20:16 a52dec
-rwxr-xr-x 1 root root 11532 2017-05-04 17:43 aafire
-rwxr-xr-x 1 root root 7292 2017-05-04 17:43 aainfo
与 vi
中的其他内容一样,有几种不同的方法可以保存我们编辑的文件。我们已经介绍了 :w
命令,但我们也可能发现其他一些命令很有用。
在正常模式下,键入 ZZ
将保存当前文件并退出 vi
。同样,命令模式命令 :wq
将把 :w
和 :q
命令组合成一个,既保存文件又退出。
:w
命令还可以指定可选的文件名。这类似于“Save AS…”。例如,如果我们正在编辑 foo.txt 并想保存一个名为 foo1.txt 的替代版本,我们将输入以下内容:
xxxxxxxxxx
:w foo1.txt
注意:虽然此命令以新名称保存文件,但它不会更改我们正在编辑的文件的名称。当我们继续编辑时,我们仍将编辑 foo.txt ,而不是 foo1.txt 。
回到【第8章.高级键盘技巧】,我们研究了编辑命令行内容的各种方法。bash使用的特定编辑命令不是任意的。它们的灵感来自emacs文本编辑器。这是bash的默认设置,但bash也支持 vi
风格的命令行编辑。使用以下命令可以轻松激活此功能:
xxxxxxxxxx
[me@linuxbox ~]$ set -o vi
完成此操作后,我们可以使用我们学到的许多 vi
风格的编辑命令。让我们试试。在命令提示符下键入以下示例文本:
xxxxxxxxxx
[me@linuxbox ~]$ the quick brown fox jumps over the lazy dog
我们可以像以前一样用箭头键移动光标,也可以用正常的方式键入字符。它这样做是因为当我们启动一个新的命令行时,编辑器处于插入模式,其行为与 vim
一样。为了得到很酷的东西,我们必须切换到正常模式。按 ESC 键退出插入模式。所有的移动命令,如yank、delete和paste,就像我们在 vim
中编辑一行文本文件一样。为了返回插入模式,我们使用适当的正常模式命令,如 i
或 A
。
将bash设置为使用 vi
风格的命令行编辑是加强我们 vi
键盘技能的好方法,而且它还有减少我们必须记住的编辑命令数量的额外好处。试试看。为了使其永久化,我们可以将 set -o vi
命令添加到 .bashrc 文件中。
要返回emacs样式编辑模式,请输入以下命令:
xxxxxxxxxx
[me@linuxbox ~]$ set -o emacs
注意:有许多在线教程可用于此功能,但请注意,大多数教程将使用传统的 vi
模式名称command
、 insert
和 ex
,而不是 vim
的 normal
、insert
和 command
。
有了这套基本技能,我们现在可以执行维护典型Linux系统所需的大部分文本编辑。从长远来看,定期学习使用 vim
会有回报。由于 vi
风格的编辑器在Unix文化中根深蒂固,我们将看到许多其他程序受到其设计的影响。 less
就是这种影响的一个很好的例子。