你应该知道的 Linux Bash 历史扩展示例
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
- 点赞
- 收藏
- 关注作者
评论(0)