3.5 快速修改并执行上一条命令

平常在使用命令行时,我经常会遇到的情况是,要么不小心,要么手太快,总之命令没有输入正确就执行了。这时候,我可不想再次重新输入命令,只想对上一条命令稍微作一下修改。那么,Shell 有没有什么快速而简便的操作方法呢?回答是肯定的,且听我慢慢道来。

3.5.1 删掉多余内容

例如,我在使用 grep 过滤日志时,不幸多输入了一个 o(原本是 lolcat):

xiaodong@codeland:~$ grep loolcat /var/log/pacman.log

我们没有必要重新输入这条命令,只需执行 ^o 即可将多余的 o 字符删除。

xiaodong@codeland:~$ ^o
xiaodong@codeland:~$ grep lolcat /var/log/pacman.log

Shell 在回显出正确的命令后立即执行了它。这里的 ^o 将上一条命令中找到的第一个 o 字符删除,从而纠正了输错的命令。

3.5.2 替换内容

让我们来看另一个例子,我在查看 file1 这个文件的内容时错输成了 flie1

xiaodong@codeland:~$ cat flie1

现在我们可以用 ^li^il 来将输错的 li 替换为 il。同样,Shell 回显出正确的命令并予以执行。

xiaodong@codeland:~$ ^li^il
xiaodong@codeland:~$ cat file1

即便在没有输错的情况下,^old^new 也是很实用的。假如我在查看 file1 后接着想查看 file4,那么只要执行 ^1^4

xiaodong@codeland:~$ cat file1
xiaodong@codeland:~$ ^1^4
xiaodong@codeland:~$ cat file4

3.5.3 全局替换

还有一种情况,有时候我们想不只替换一处,而是把上一条命令中的每处内容都替换掉。要实现这种效果,可以使用 !:gs/old/new,其中,! 表示引用上一条命令(在后续的章节中我们将详细讲解),: (冒号) 后边的 gs 意为全局(g)替换(s),/old/new 则与 ^old^new 相似。

xiaodong@codeland:~$ ansible nginx -a 'which nginx'

这条命令让我通过 Ansible 了解 nginx 分组的所有机器是否都包含 nginx 程序。接下来,我想看看 haproxy 分组的情况,于是我执行:

xiaodong@codeland:~$ !:gs/nginx/haproxy
xiaodong@codeland:~$ ansible haproxy -a 'which haproxy'

顺便提一句,在 zsh 中除了支持上述方式外,也可以使用:

xiaodong@codeland:~$ ansible nginx -a 'which nginx'
xiaodong@codeland:~$ ^nginx^haproxy^:G
xiaodong@codeland:~$ ansible haproxy -a 'which haproxy'