4.2 Emacs 编辑模式实战
4.2.1 按字移动和删除
让我们先在命令行输入一些字符,然后来看看如何一个一个的移动字符:
糟糕,我将“黑客”错输成了“骇客”,现在我要将光标向左移到“客”字,接着删除“骇”字,然后再重新输入正确的“黑”字。
对于命令行新手来说,可能会使用左方向键(←)向左移动字符。好,我们来试一下。按 3 下左方向键(←),于是光标停留在“客”字上。此时,我们再按退格键则删除光标左边的“骇”字。我们接着重新输入正确的“黑”字。因为我们还要继续输入新的内容,所以按 3 下右方向键(→)往右移动光标,直到行尾。之后,我们能够再输入新的内容“使用命令行”。
在上面的操作中,我们通过分别按左方向键(←)和右方向键(→)来向左或往右移动一个字符。利用 Emacs 编辑模式,其实有比按左右方向键更好的操作方法。因为左右方向键通常远离键盘中心区域,所以与 Emacs 编辑模式提供的操作方法比起来在效率上会有所降低。
下面,我们就用 Emacs 编辑模式所提供的操作方法来一个个的移动字符。在 Emacs 编辑模式中,向左移动一个字符可以按 Ctrl + b。因此,我们按 3 次 Ctrl + b,此时光标位于“客”字上。同样的,我们通过按退格键来删除“骇”字。在输入“黑”字后,我们需要将光标移到最右边。现在,我们可以按 Ctrl + f,以便往右移动一个字符。需要往右移动几个字符就按几下 Ctrl + f。顺便说一句,在后面的内容中,我们会讲到如何一下子就移到最右边的操作方法。此刻,就先让我们熟悉按字移动的操作吧。
上述操作中我们使用退格键删除光标左边的字符。假如我们向左多移动了一个字符,那么此时光标将在“骇”字上。要想删除“骇”字,难道再往右移动吗?当然不必。Emacs 编辑模式为我们提供了 Ctrl + d 来删除光标下的字符。
在此,我们再介绍一组快捷键:Ctrl + t。这组按键的作用是将光标左边的两个字符交换顺序。例如,当我在输入
后,通过按下 Ctrl + t 便能够将其变成 ls
。
总结起来,按字移动和删除的操作方法参考表 4.1。
按键 | 作用 |
---|---|
Ctrl + b | 向左移动一个字符 |
Ctrl + f | 往右移动一个字符 |
退格键 | 删除光标左边的字符 |
Ctrl + d | 删除光标下的字符 |
Ctrl + t | 将光标左边的两个字符交换顺序 |
4.2.2 按“词”移动和删除
按字符移动和删除毕竟有些琐碎,为了完成某个操作,有时候需要我们按下很多次快捷键。有鉴于此,Emacs 编辑模式针对“词”这个更大的范围提供了移动和删除的操作方法。值得注意的是,我们在此给“词”添加了引号。换句话说,这里的“词”是 Shell 所理解的“词”的含义,与现实生活中所谓的词含义并不相同。在 bash 中,“词”即字母和数字的组合,例如 file1 这种,其中并不包含特殊字符在内。而在 zsh 中,对“词”的界定跟 bash 又有所不同,除了字母和数字之外,还包括比如 *
、?
、_
、-
等这样的符号。通过变量 WORDCHARS
,我们可以看到这类字符到底有哪些。在我的系统中,执行
后,可以见到有如下字符:
如果你想要让 zsh 判定“词”的行为跟 bash 一样的话,那么不妨将 WORDCHARS
变量的值设为空:
下面我们来看一个按“词”移动和删除的操作例子:
在我输入该命令行后,忽然想到应该查询 lolcat
这个包。为了将 figlet
改成 lolcat
,我按 Alt + b 向左一个“词”一个“词”的移动。按 5 下后,此时光标停留在 figlet
的 f
上。接着,我按 Alt + d 删除光标右边的“词”(也就是 figlet
)。然后输入新的内容 lolcat
。
现在,如果不需要再输入内容的话,则可以直接按回车键执行命令。但因为我还想将标准输出的内容保存起来,所以继续按 Alt + f 来往右按“词”移动。当抵达最右边时,再输入新的内容 > /tmp/output.log
。此刻,我们的命令行是:
最后,我按 Alt + 退格键(或 Ctrl + w)删除光标左边的 log
,并输入 txt
来完成该命令行的编辑。
正如前面所述,在 zsh 中按“词”移动的行为跟 bash 略有不同。这是因为它们对“词”界定的含义不一样的缘故。我们仍旧以上面的例子来加以说明。在光标都位于该命令行最右边的情况下,bash 中按 Alt + b 向左移动到的是 txt
中开头的 t
上;而在 zsh 中同样的操作却移动到了 /tmp/output.txt
开头的 /
。在此,我们可以发现 zsh 将 /
和 .
都看作“词”的一部分。两个 Shell 比较起来,zsh 移动更快,按键也更少,但是粒度却要粗一些。因为 zsh 对“词”的界定范围比 bash 更宽,所以对“词”的删除内容也更多。bash 中按 Alt + d 删除的是 txt
,而 zsh 中删除的却是 /tmp/output.txt
。
需要特别指出的是,通过 Alt + 退格键 和 Alt + d 删除的内容,Shell 并没有丢弃,而是将其保存在 kill ring 中。你可以将 kill ring 看作一个特殊的剪贴板。当然,它里面的内容我们也是可以获取的。我们只需按 Ctrl + y 即可获取上次删除的内容。
此外,与 Ctrl + t 交换光标左边的两个字符相似,Alt + t 能够用来交换光标左边两个“词”的顺序。例如:
当我们按 Alt + t 后,该命令行将变成:
以下介绍的几组快捷键用于更改“词”的大小写。例如,我们在命令行输入
并按 Alt + b 将光标移到 f
上后,此时,按 Esc + c 把 foo
变成 Foo
;若是按 Esc + u,则将变为 FOO
;最后,按 Esc + l,又将成为 foo
。
按“词”移动和删除的操作方法参考表 4.2。
按键 | 作用 |
---|---|
Alt + b | 向左移动一个“词” |
Alt + f | 往右移动一个“词” |
Alt + 退格键 | 删除光标左边的“词” |
Ctrl + w | 同上 |
Alt + d | 删除光标右边的“词” |
Ctrl + y | 获取上次删除的内容 |
Alt + t | 交换光标左边两个“词”的顺序 |
Esc + c | 将光标右边的“词”的开头字母变成大写 |
Esc + u | 将光标右边的“词”全部更改为大写字母 |
Esc + l | 将光标右边的“词”全部更改为小写字母 |
4.2.3 按行移动和删除
比“词”范围更大的移动及删除操作是行。相对“词”而言,我们只需要更少的按键即可移到更广的区域。由此,也将删除更多的命令行内容。让我们通过一个例子来说明:
在此,我想找出当前目录中包含 set
的所有文件。假如我想将这行命令改成:
首先,我按 Ctrl + a 将光标移到该命令行的行首(也就是最左边)。接着输入 e
将命令改成 egrep
。然后,我再按 Ctrl + e 将光标移到此行的结尾处(也就是最右边)。在通过 Alt + 退格键 删除 txt
后,重新输入 md
即可完成对该命令行的修改。
下面,我们来看看针对行的删除操作。依然请出我们的老朋友 foo
、bar
、baz
:
我们先按两下 Alt + b 将光标移到 bar
的 b
上。现在,如果我们打算删除 bar
和 baz
,那么只要按 Ctrl + k;反之,但假设我们想要删除 echo
及 foo
的话,则需按 Ctrl + u。值得说明的是,在 zsh 中,Ctrl + u 的行为与 bash 中并不相同,它是删除整行的全部内容。
按行移动和删除的操作方法参考表 4.3。
按键 | 作用 |
---|---|
Ctrl + a | 将光标移到行首(最左边) |
Ctrl + e | 将光标移到行尾(最右边) |
Ctrl + k | 从光标处往右删除至行尾 |
Ctrl + u | 从光标处向左删除至行首 |
4.2.4 Emacs 编辑模式总结
从前面我们所讲的内容来看,Emacs 编辑模式的内容编辑范围主要包括下列 3 种:
- 字
- “词”
- 行
针对每一种范围,又包含两种编辑操作,分别为移动和删除。如图 4.1 所示。