你应该知道的 Linux Bash 历史扩展示例

举报
Tiamo_T 发表于 2022/05/10 07:43:40 2022/05/10
【摘要】 Bash 历史非常强大。了解如何有效地使用 bash 历史扩展将使您在 Linux 命令行上的工作效率极高。

Bash 历史非常强大。了解如何有效地使用 bash 历史扩展将使您在 Linux 命令行上的工作效率极高。

本文解释了 15 个使用以下 bash 历史扩展功能的示例:

  • 事件指示符——指历史中的特定命令。它以 !
  • 词指示符——指历史条目的特定词。通常,这与偶数指示符结合使用。甚至指示符和单词指示符也用冒号分隔
  • 修饰符 - 修改由事件或单词指示符完成的替换结果


本文是我们正在进行的Bash 教程系列的一部分。

如您所知,要查看所有历史条目,请使用 history 命令。这将显示之前执行的所有命令以及历史表中该命令的编号。

$ history
1 tar cvf etc.tar /etc/
2 cp /etc/passwd /backup
3 ps -ef | grep http
4 service sshd restart
5 /usr/local/apache2/bin/apachectl restart

Bash 历史事件指示符

1. 使用 !n 执行历史记录中的特定命令

如果您之前执行过一个命令,无需再次重新键入,您可以使用历史记录中相应的命令编号快速执行该命令。

例如,要执行命令 #4,请执行以下操作。这将显示历史记录中的命令#4,并立即执行。


$ !4
service sshd restart

要执行输入了 2 个命令的命令,请执行以下操作。

$!-2

要执行上一个命令,请执行以下任一操作:

$ !!

$ !-1

您也可以按 <Ctrl>-P(如果您处于默认的 emacs 模式)来访问上一个命令。

如果您使用“set -o vi”为命令行启用了 vi 样式编辑,请使用 <Esc>-k 进入上一个命令。

2. 使用 !string 和 !?string 执行带有关键字的命令

您还可以使用关键字来执行历史记录中的命令。

以下示例将搜索以关键字“ps”开始的先前命令并执行它。在这个例子中,它选择了前面的命令“ps -ef | grep http”并执行它。

$ !ps
ps -ef | grep http

以下示例将搜索包含关键字“apache”的先前命令并执行它。在这个例子中,它选择了前面的命令“/usr/local/apache2/bin/apachectl restart”并执行它。

$ !?apache
/usr/local/apache2/bin/apachectl restart

3. 使用 ^str1^str2^ 替换上一个命令中的字符串

在以下示例中,首先我们执行 ls 命令来验证文件。后来我们意识到我们要查看文件的内容。无需再次输入整个文件名,我们只需将上一个命令中的“ls”替换为“cat”,如下所示。

$ ls /etc/cron.daily/logrotate

$ ^ls^cat^
cat /etc/cron.daily/logrotate

Bash 历史词指示符

当您要键入新命令但使用之前执行的命令之一的参数时,单词指示符非常有用。一些示例如下所示。

4. 使用 :^ 获取命令的第一个参数

在以下示例中,“!cp:^”作为“ls -l”命令的参数给出。“!cp:^”定位历史中以“cp”开头的前一个命令,并获取该命令的第一个参数。

$ cp /etc/passwd /backup

$ ls -l !cp:^
ls -l /etc/passwd

以下示例从上一个命令中获取第一个参数。

$ ls -l !!:^

5. 使用 :$ 获取命令的最后一个参数

在以下示例中,“!cp:$”作为“ls -l”命令的参数给出。“!cp:$”定位历史中以“cp”开头的上一个命令,并获取该命令的最后一个参数。

$ cp /etc/passwd /backup

$ ls -l !cp:$
ls -l /backup

以下示例从上一个命令中获取最后一个参数。

$ls -l !!:$

6. 使用 :n 获取命令的第 n 个参数

在以下示例中,“!tar:2”作为“ls -l”命令的参数给出。“!tar:2”定位历史中以“tar”开头的上一个命令,并获取该命令的第二个参数。

$ tar cvfz /backup/home-dir-backup.tar.gz /home

$ ls -l !tar:2
ls -l /backup/home-dir-backup.tar.gz

7. 使用 :* 从命令中获取所有参数

在以下示例中,“!cp:*”作为“ls -l”命令的参数给出。“!cp:*”定位历史中以“cp”开头的上一个命令并获取它的所有参数。

$ cp /etc/passwd /backup

$ ls -l !cp:*
ls -l /etc/passwd /backup

8. 使用 !% 引用最近搜索过的词

正如我们上面解释的,“!?apache”将搜索包含关键字“apache”的先前历史命令并执行它。

$ /usr/local/apache2/bin/apachectl restart

$ !?apache
/usr/local/apache2/bin/apachectl restart

!% 将引用与前一个“?”匹配的整个单词 搜索。

例如,如果您之前搜索过“?apache”,“!%”将匹配整个单词“/usr/local/apache2/bin/apachectl”。请注意,“/”在此上下文中被视为一个单词的一部分。

因此,在这种情况下,通过执行以下命令,您可以停止 apache。

$ !% stop
/usr/local/apache2/bin/apachectl stop

9. 使用 xy 从命令中获取参数范围

在以下示例中,“!tar:3-5”作为“ls -l”命令的参数给出。“!tar:3-5”定位历史中以“tar”开头的上一个命令,并获取从 3 到 5 的参数。

$ tar cvf home-dir.tar john jason ramesh rita

$ ls -l !tar:3-5
ls -l john jason ramesh

以下从 2 中获取所有参数。

$ ls -l !tar:2-$

请注意以下事项:

  • !!:* 获取上一个命令的所有参数
  • !!:2* 获取从第二个参数开始的所有参数。
  • !!:2-$ 同上。获取从第二个参数开始的所有参数。
  • !!:2- 获取从第二个参数开始的所有参数(最后一个参数除外)。

Bash 历史修改器

修饰符在词代号之后给出,如下面的例子中所解释的。

10. 使用 :h 从单词中删除尾随路径名

在以下示例中,“!!:$:h”采用上一个命令的最后一个参数,并删除尾随路径名。在这种情况下,它会删除文件名,并且只获取完整路径。

$ ls -l /very/long/path/name/file-name.txt

$ ls -l !!:$:h
ls -l /very/long/path/name

11. 使用 :t 从单词中删除所有前导路径名

这与前面的例子完全相反。

在以下示例中,“!!:$:t”采用上一个命令的最后一个参数,并删除所有前导路径名。在这种情况下,它只获取文件名。

$ ls -l /very/long/path/name/file-name.txt

$ ls -l !!:$:t
ls -l file-name.txt

12. 使用 :r 从单词中删除文件扩展名

在以下示例中,“!!:$:r”采用上一个命令的最后一个参数,并仅删除“.suffix”(此处为文件扩展名)。在这种情况下,它删除了 .txt

$ ls -l /very/long/path/name/file-name.txt

$ ls -l !!:$:r
ls -l /very/long/path/name/file-name

13. 使用 :s/str1/str2/ 替换 bash 历史中的 Sed 类

除了使用我们之前讨论的“^original^replacement^”,我们还可以在 bash 历史记录中使用类似sed 的替换,如下例所示。这可能很容易记住。!!是调用前面的命令,“:s/original-string/replacement-string/”是替换字符串的类似sed的语法。

$ !!:s/ls -l/cat/

您还可以使用 g 标志(与 s 标志一起)进行全局替换,如下所示。当您输入错误的多个单词并希望一起更改所有单词并再次执行命令时,这很有帮助。

在下面的例子中,我错误地给出了两次“password”(而不是 passwd)。

$ cp /etc/password /backup/password.bak

要解决此问题,只需执行以下全局历史 sed 类似替换。

$ !!:gs/password/passwd/
cp /etc/passwd /backup/passwd.bak

14. 使用 :& 快速重复替换

如果您已经如上所示成功执行了 bash 历史记录替换,则可以使用 :& 再次快速重复相同的替换。

我在另一个命令中错误地再次输入了“password”而不是“passwd”。

$ tar cvf password.tar /etc/password

现在,我可以使用“:&”,而不是重新输入命令,或者执行“gs/password/passwd”,这将重用最后一个替换。使用“:g&”全局重用最后一个替换。

$ !!:g&
tar cvf passwd.tar /etc/passwd

15. 使用 :p 打印命令而不执行它

这在您进行复杂的历史替换时非常有用,并且您想在执行之前查看最终命令。

在以下示例中,“!tar:3-:p”并没有真正执行命令。

由于我们在这里给出了“:p”,它只是进行替换并显示新命令。一旦您验证了 bash 历史扩展,并且如果您认为这是您要运行的命令,请删除“:p”并再次执行它。

$ tar cvf home-dir.tar john jason ramesh rita

$ tar cvfz new-file.tar !tar:3-:p
tar cvfz new-file.tar john jason ramesh
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。