如何撤消命令历史记录中的更改?

fed*_*qui 18 bash command-history readline

在 UNIX 系统中,您可以按顶部和底部箭头来浏览前面的命令。这非常方便。

有时,我会上去找到一个我想再次使用的命令,但有一些变化。如果我进行了这样的更改,那么我就没有办法恢复原来的命令,除非我在history.

有什么方法可以“撤消”通过键访问的历史记录中对命令的更改?

我目前的解决方法是#在命令前加上 a 。这样,当前命令作为注释执行,所以什么也没有发生。然后,我可以使用按键再次浏览命令。问题是我使用的命令可能在列表中很远,所以再次上升 200 次有点 。Control + R 也不是解决方案,因为我可能不记得我在找什么。

例子

我输入了以下“50个命令前”:

ls -l /etc/httpd/conf/
Run Code Online (Sandbox Code Playgroud)

现在我走到那条线并将其更改为

ls -l /etc/init.d/
Run Code Online (Sandbox Code Playgroud)

但没有按回车键。现在,我想ls -l /etc/httpd/conf/再次到达。

我的环境

$ echo $SHELL
/bin/bash
$ echo $TERM
xterm
Run Code Online (Sandbox Code Playgroud)

Gil*_*il' 15

只要您编辑了历史条目但尚未按下Enter,要返回原始条目,请重复按Ctrl+ _undo命令 — 直到它不再进行任何进一步更改。您将返回到原始条目。


iyr*_*rin 7

对行进行多次更改后,恢复到原始命令

revert-line (M-r) 
    Undo all changes made to this line. This is like 
executing the undo command enough times to get back to the beginning.
Run Code Online (Sandbox Code Playgroud)

M 是元键,即 alt</kbd+r for me.


无偿但有用的信息

当你已经执行像OP命令以前做(它发生),没有什么可以“撤销”,因为这些命令是由处理和记忆GNU的Readline库,并且不写入$HISTFILE直到shell退出。我提到这一点的原因是因为你不能只grep$HISTFILE像人们所预料的,它可能不是理想的退出外壳。

所以这里有几个选项可以让您免于回滚以前的所有 readline 命令。

如果您记得某些命令,请按ctrl+r并键入您记得的内容以搜索包含该字符串的先前命令。再次按ctrl+r将显示下一个最近的,向后搜索。

例如,键入ls -lthen ctrl+r查找您要查找的上一个命令所需的次数。如果滚动过去,ctrl+s 将从当前位置向前搜索。

fc内建命令的bash是有帮助的列表中的索引号以前一起readline的命令。

fc -l -100 将在 readline 中列出前 100 个命令。

此外,如果 OP 知道他正在寻找以前的ls -l命令,他可以将输出通过管道传输到grep例如:fc -l -100 | grep 'ls -l'

这应该输出以ls -l索引号开头的先前命令的列表。输出如下所示:
2065 ls -l

现在您可以使用事件指示符!nwheren是索引号。在这个例子中,执行!2065将扩展到ls -l.


虽然没有在事后帮助,任何人都希望修改以前的命令时,应该看到保存最近命令历史记录HISTORY EXPANSION的部分man bash。以下是一些修改旧命令而不覆盖历史记录的替代方法。

Event Designators部分显示了如何从最近使用的命令轻松编辑字符串。

^string1^string2^
              Quick  substitution.  Repeat the previous command, replacing string1 with string2.  Equivalent to
              ``!!:s/string1/string2/'' (see Modifiers below).
Run Code Online (Sandbox Code Playgroud)

例子:

$ echo foo
foo 
$ ^foo^bar
echo bar
bar
Run Code Online (Sandbox Code Playgroud)

最近的命令现在将显示:

echo foo
echo bar
Run Code Online (Sandbox Code Playgroud)

上面的示例还说明了如何使用sed替换事件指示符中的字符串。

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

因此,如果历史记录中有 3 个命令,echo foo那么您将使用:
!-3:s/foo/bar

请注意,事件指示符将作为命令执行出现在您的历史记录中,在本例中为echo bar。它不会出现在历史记录中!-3:s/foo/bar

只是将它扔在那里,因为它似乎密切相关,即使它更像是“不做”而不是 OP 正在寻找的“撤消”解决方案。