在脚本和别名中使用 bash 的 bang 命令(例如 '!!')?

Byt*_*der 7 command-line bash scripts bashrc bash-history

是否可以在 bash 脚本和 bash 别名中使用所谓的 bang 命令(!+ 命令/符号,如 eg!!!$:p)?

我想添加行

alias getit='sudo apt-get install !!'
Run Code Online (Sandbox Code Playgroud)

到我的~/.bashrc文件,以便能够通过getit在对命令本身的非成功调用之后键入来安装未找到的命令,类似于工具The Fuck的行为,只是少说脏话......

但是,该行不起作用,如下面的输出所示:

$ cowsay
The application »cowsay« is currently not installed.
You can install it by typing:
sudo apt-get install cowsay

$ getit
Reading package lists... Done
Building dependency tree       
Reading state information... Done
E: Unable to locate package !!

$ 
Run Code Online (Sandbox Code Playgroud)

请注意,我自己从德语翻译了第一个命令的输出,因为它LANG=C没有用......无论出于何种原因。

无论如何,您可以看到别名中的 bang-command 不会被解释为被上次执行的命令替换,而是保持相同的字符串。我已经发现 bang-commands 通常只在交互式 shell 中工作,因此不在脚本中。

是否可以更改此设置,以便!!将其解释为脚本中最后执行的命令字符串?别名怎么样,有可能吗?

mur*_*uru 12

历史扩展在别名扩展之前完成,因此您必须使用history内置函数自己执行扩展:

alias getit='sudo apt-get install $(history -p !!)'
Run Code Online (Sandbox Code Playgroud)

然而,上面的别名使用整个最后执行的命令作为 for 的参数sudo apt-get install,这意味着如果我们给失败的命令提供了一个参数(如cowsay "Hello"),我们现在也会在要安装的包列表中显示这个参数(sudo apt-get install cowsay "Hello")。

由于这不是故意的,我们应该按照steeldriver建议修改别名,并使用!:0而不是!!仅获取第一个单词(命令名称):

alias getit='sudo apt-get install $(history -p !:0)'
Run Code Online (Sandbox Code Playgroud)

我们仍然需要注意这个过程只有在失败的命令名称和它的包名称相同时才有效。例如,它不适用于命令lynx(CLI 浏览器),因为它包含在包中lynx-cur