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


12

在UNIX系统中,您可以按上下箭头浏览先前的命令。这非常方便。

有时,我会上去查找要再次使用的命令,但是会有一些变化。如果我做了这样的更改,那么除非我签入,否则我将无法取回原始命令history

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

我当前的解决方法是#在命令前添加a 。这样,当前命令将作为注释执行,因此没有任何反应。然后,我可以再次通过按键浏览命令。问题是我使用的命令可能在列表中距离很远,因此再次向上执行200次会有点麻烦。Control + R也不是解决方案,因为我可能不记得确切要找什么。

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

ls -l /etc/httpd/conf/

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

ls -l /etc/init.d/

但没有按Enter。现在,我想ls -l /etc/httpd/conf/再说一遍。

我的环境

$ echo $SHELL
/bin/bash
$ echo $TERM
xterm

更改命令历史记录可能是您正在使用的Shell的(错误)功能。ksh例如,在中,您可以编辑历史记录条目并调用它们,而无需删除条目的“先前版本”。您具有所有可用的调用命令。
Janis

有了“它更改”,我的意思是:给定一个我在用箭头到达它后更改的上一个命令,如果我用箭头上下移动,则旧命令将不会显示原来的样子,而是我修改的样子它。当然,如果我键入“ enter”执行命令,那么旧命令将与最初的命令相同。但这恰恰是我试图避免的事情,并且正在寻找一种将命令“重置”为其初始值的方法。
fedorqui's

1
同样在这种情况下,ksh似乎的行为也有所不同。您的历史记录编辑选项还取决于所选的编辑模式。ksh例如,在的vi模式下,旧条目不会被覆盖,我也可以vi使用'u' 发出撤消命令,例如in 。
Janis

嗯,这听起来很有希望。我现在在Bash工作,目前不考虑更改为ksh,但是很高兴知道那里存在这种东西。
fedorqui's

我想知道bash在关闭外壳时将最近的命令历史记录存储在哪里,然后再写入历史记录文件。这可能有助于确定这是否可能。有人吗 我以为它可能在shell变量之一中,但是现在没有时间仔细阅读手册。
iyrin

Answers:


10

只要您已编辑历史记录条目但尚未按Enter,就可以返回到原始条目,重复按Ctrl+ _- undo命令-直到不做任何进一步更改。您将返回原始条目。


5

对行进行了多次更改后,请还原为原始命令

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.

M是元密钥,这altr对我来说。


免费但有用的信息

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

因此,这里有两个选项可避免您回滚到所有以前的readline命令。

如果您记得某些命令,请按ctrl+ r并键入您要记住的内容,以搜索包含该字符串的先前命令。再次按ctrl+ r将显示倒数第二个最新的。

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

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

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

此外,如果OP知道他正在寻找先前的ls -l命令,则可以将输出传递给以下命令grepfc -l -100 | grep 'ls -l'

这将输出一个先前ls -l命令的列表,并在其前加一个索引号。输出看起来像这样:
2065 ls -l

现在,您可以使用事件指示符!n,其中n的索引号为。在此示例中,执行!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).

例:

$ echo foo
foo 
$ ^foo^bar
echo bar
bar

现在,最新命令将显示:

echo foo
echo bar

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

!-n    Refer to the current command minus n.

因此,如果历史记录中有3条命令,echo foo则可以使用:
!-3:s/foo/bar

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

只是把它扔掉,似乎紧密相关,即使它比OP寻找的“撤消”解决方案更多是“不要做”。


很好,非常感谢您提供详细信息。我接受Gilles的回答,因为它完全符合我的期望,而在这里您假设我了解有关要重做的命令的很多事情,但并非总是如此。
fedorqui

是的,我同意。如果将撤消功能扩展到我以前以某种方式输入的命令,那就太好了。
iyrin 2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.