如何重新运行倒数第二个命令?

coc*_*mac 20 command-line bash bash-history

我使用的是 Ubuntu 21.10。如果我搞砸了,我可以使用 重新运行最后一个命令!!。这是一个例子:

$ apt update
Reading package lists... Done
E: Could not open lock file /var/lib/apt/lists/lock - open (13: Permission denied)
E: Unable to lock directory /var/lib/apt/lists/
W: Problem unlinking the file /var/cache/apt/pkgcache.bin - RemoveCaches (13: Permission denied)
W: Problem unlinking the file /var/cache/apt/srcpkgcache.bin - RemoveCaches (13: Permission denied)
$ sudo !!
sudo apt update
[sudo] password for [me]:
...
Fetched 336 kB in 2s (206 kB/s)
Reading package lists... Done
Building dependency tree
Reading state information... Done
98 packages can be upgraded. Run 'apt list --upgradable' to see them.
Run Code Online (Sandbox Code Playgroud)

很好,但是我如何运行之前的命令,而不是重新运行上一个命令?像这样:

$ echo hi
hi
$ echo hello
hello
$ !!   <-- I'm trying to get that to run 'echo hi'
hello
Run Code Online (Sandbox Code Playgroud)

基本上,这就是我要找的

$ echo hi
hi
$ echo hello
hello
$ ???   <-- What can I put here to get it to run 'echo hi'?
echo hello!
hello!
Run Code Online (Sandbox Code Playgroud)

那么,考虑到!!运行最后一个命令,我怎样才能在上一个命令之前运行该命令呢?在我的示例中,!!我可以运行什么来执行而不是键入echo hi

Gor*_*son 41

您可以使用up-arrowdown-arrow键循环浏览命令历史记录。因此,要重新运行倒数第二个命令,您需要按up-arrow两次,然后按return

与诸如 之类的方法相比,这有几个优点!-2。最重要的是(在我看来),您可以看到该命令并确保它是您打算在按回车键执行之前重新运行的命令。即使除了简单的错误(“哎呀,我猜这是我想要的第三个命令”),bash 历史记录可能不会按照您期望的方式计算先前的命令,因为ignorespaceignoredupsHISTCONTROL等选项。

此外,交互式命令调用使您可以在重新运行命令之前轻松编辑命令。您也可以使用历史调用修改器来执行此操作,但再次以交互方式执行此操作可以让您在执行调用/修改的命令之前查看您的编辑。

另外,如果你像我一样懒,up-arrow up-arrow return输入比(shift)exclamation minus 2 return

  • “最重要的是(在我看来),您可以看到该命令并确保它是您打算重新运行的命令,然后再按回车键执行它。” 如果启用“histverify”,则任何具有历史替换的命令都需要在由 shell 解析之前进行确认。然而,我和你一样懒,所以在这种特殊情况下我会赞成你的建议。 (3认同)

ste*_*ver 38

来自HISTORY EXPANSION以下部分man bash

!-n    Refer to the current command minus n
Run Code Online (Sandbox Code Playgroud)

因此,要运行最后一个命令,您可以使用!-2

事实上,!!只是一个同义词!-1

  • @MikeMaxwell,在这种情况下,0 是您当前输入的内容;-1 是前一个命令,-2 是前一个命令。对于我,这说得通 :-) (9认同)
  • 你的意思是计算机科学家向前时从零开始计数,向后时从-1开始计数?这些书呆子从哪里学会数数的? (4认同)

Oli*_*lac 7

!-n执行您历史记录中的命令“-n”,但我不推荐它,因为它是“即时”的,不会给您时间首先检查“第 N”命令是否是您需要再次执行的正确命令。 (@bac0n 很好地指出,您可以设置 :shopt -s histverify将其切换为“非即时”:它会让您在执行命令之前验证命令 !-n 扩展为<Enter>

但是,如果您使用bashshell,我更推荐使用搜索功能:

Ctrl 然后键入something,这是您要查找的命令的一部分。(例如:Ctrl++ r(在终端中输入)echo

它将显示您的历史匹配中最新出现的情况(即匹配您在+something之后键入的搜索词)。Ctrlr

接下来的Ctrl+r将进一步回顾你的历史。或者添加字母将使搜索更加精确。

一旦找到合适的匹配项,请按Enter再次执行(或Ctrl+c退出搜索而不执行当前显示的匹配命令)。

附加提示:如果Enter您按Ctrl+ 而不是按 + o,它将执行选定的历史命令并显示下一个,准备好执行Enter(仅执行该命令并返回到正常提示符)或再次Ctrl+ o(执行它)并显示历史记录中的下一个命令)。重复一系列步骤并在执行这些命令之前提供这些命令的显示非常有用。

每次使用这些东西时,您都可以更改当前显示的行上的某些内容(使用向左或向右箭头键在其中移动),例如参数、服务器名称等,并执行修改后的行+ 转到下一个(如果您按Ctrl+ o)。

  • 这取决于您如何设置 shell 选项...如果您不想直接运行该条目,可以附加“shopt -s histverify”。 (3认同)

Lat*_*kar 5

如果你跑

history
Run Code Online (Sandbox Code Playgroud)

您将获得最后输入的“n”个命令的列表。历史记录大小默认为 500 个命令。因此,正如 Steeldriver 所解释的,最后一个命令之前的命令可以重新运行

!-2
Run Code Online (Sandbox Code Playgroud)

是的,倒数第三个将是

!-3
Run Code Online (Sandbox Code Playgroud)

等等。有关更多详细信息,请使用

man history
Run Code Online (Sandbox Code Playgroud)

并搜索事件指示符

  • 一个小补充:您可以仅使用 `!312` 来运行历史记录中的特定命令(以运行历史记录输出中显示的行号 312 的命令)。更有用的提示:如果您在该命令中出现拼写错误,您可以运行`!312:p`,它不会执行该命令,但仍将其作为“上次使用的命令”放在顶部。这可以帮助您编辑较长的命令,而无需从历史记录中手动复制粘贴,只需使用向上箭头并在运行之前编辑命令即可。 (3认同)