如何在 bash 中执行最后一行输出?

Tim*_*Tim 16 bash

我知道我可以在 bash 中运行最后一个命令!!,但如何运行最后一行输出?

我在考虑这个输出的用例:

The program 'git' is currently not installed. You can install it by typing:
sudo apt-get install git
Run Code Online (Sandbox Code Playgroud)

但我不知道我怎么能运行它。我在想类似的东西!!,也许@@或类似的?


超级用户也有这个问题。

hee*_*ayl 21

该命令$(!! |& tail -1)应该执行以下操作:

$ git something
The program 'git' is currently not installed. You can install it by typing:
sudo apt-get install git

$ $(!! |& tail -1)
$(git something |& tail -1)
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following extra packages will be installed:
git-man liberror-perl
Run Code Online (Sandbox Code Playgroud)

如您所见,sudo apt-get install git命令正在运行。

编辑:分解$(!! |& tail -1)

  • $()bash命令替换模式

  • bash将扩展!!到最后执行的命令

  • |&部分很棘手。通常 pipe|将采用左侧命令的 STDOUT 并将其作为 STDIN 传递给右侧的命令|,在您的情况下,前一个命令将其输出作为错误消息打印在 STDERR 上。因此,这样做|无济于事,我们需要将 STDOUT 和 STDERR(或仅 STDERR)传递给右侧命令。|&将 STDOUT 和 STDERR 都作为 STDIN 传递给右侧命令。或者,更好的是您只能通过 STDERR:

    $(!! 2>&1 >/dev/null | tail -1)
    
    Run Code Online (Sandbox Code Playgroud)
  • tail -1像往常一样将打印其输入的最后一行。在这里,您可以更精确地打印包含apt-get install命令的行,而不是打印最后一行:

    $(!! 2>&1 >/dev/null | grep 'apt-get install')
    
    Run Code Online (Sandbox Code Playgroud)

  • 您的方法假设第二次输出相同。某些命令可能会在下一次产生不同的输出,在这种情况下,很难预测执行其输出的最后一行实际上会做什么。 (2认同)

Eli*_*gan 9

特尔;博士: alias @@='$($(fc -ln -1) |& tail -1)'

Bash 的历史交互工具不提供任何机制来检查命令的输出shell 不存储那个,历史扩展专门用于您自己运行的命令或这些命令的一部分。

这留下了重新运行最后一个命令并将stdoutstderr ( |&)管道化到命令替换中的方法。heemayl 的回答实现了这一点,但不能在别名中使用,因为 shell 在扩展别名之前而不是之后执行历史扩展。

我也无法让历史扩展在 shell 函数中工作,即使在带有set -H. 我怀疑!!在一个函数中永远不会被扩展,我不确定它会被扩展成什么,但现在我不确定为什么不是。

因此,如果您想设置一些东西以便只需很少的输入就可以做到这一点,您应该使用fcshell 内置而不是历史扩展来从历史中提取最后一个命令。这还有一个额外的优势,即使历史扩展被禁用,它也能工作。

戈登戴维森创建包含 bash 历史扩展的别名(在超级用户上)的回答所示,模拟. 在heemayl 的命令中插入它会产生:$(fc -ln -1)!!!! $(!! |& tail -1)

$($(fc -ln -1) |& tail -1)
Run Code Online (Sandbox Code Playgroud)

这就像$(!! |& tail -1)但可以进入别名定义:

alias @@='$($(fc -ln -1) |& tail -1)'
Run Code Online (Sandbox Code Playgroud)

在您运行该定义,或将其放入.bash_aliases.bashrc启动一个新的 shell 之后,您可以简单地键入@@(或任何您命名的别名)来尝试执行最后一个命令的最后一行输出。

ek@Io:~$ alias @@='$($(fc -ln -1) |& tail -1)'
ek@Io:~$ evolution
The program 'evolution' is currently not installed. You can install it by typing:
sudo apt-get install evolution
ek@Io:~$ @@
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following extra packages will be installed:
  evolution-common evolution-data-server evolution-data-server-online-accounts
....
Run Code Online (Sandbox Code Playgroud)