大约每天一次,当我在 bash 中搜索历史记录项时,我会遇到一个问题。操作该项目有时会删除历史记录条目,有时则不会。
这是发生这种情况的一个案例:
$ls foo
ls: No such file or directory
# (ctrl-r)ls foo(tab)
$ ls foo
# (ctrl-a)(ctrl-k)
$
# (ctrl-r)ls foo
# (no matches)
对这里发生的事情有何解释?
答案1
我认为这种行为的原因是 Bash 如何处理先前历史行的修改。previous-history
( C- p) 或reverse-search-history
( C- )等命令的作用r是获取以前的历史条目:
previous-history (C-p)
Fetch the previous command from the history list, moving back in the list.
当上一个历史条目是取来的它的打印方式就像打字一样。现在,您可以只修改它但不能执行(如您的示例中所示)或修改并执行它。当您执行它时,您会调用accept-line
:
accept-line (Newline or Return)
Accept the line regardless of where the cursor is. If this line is
non-empty, add it to the history list according to the setting of
the HISTCONTROL and HISTIGNORE variables. If this line is a
modified history line, then restore the history line to its
original state.
按下后,Return修改的行将保存到历史记录中,而原始行将保持不变。但是,让我们考虑一下,如果您只是修改获取的行而不按,会发生什么Return- 它被修改但未执行,因此accept-line
不会被调用。原来的历史线变成了修改的。
要在实践中看到这一点,请将此行添加到您的~/.inputrc
并启动新的子 shell:
set mark-modified-lines On
现在让我们按照您的示例执行相同的操作:
$ echo April # 0) press Return - `accept-line` is called
# 1. press C-r and type `April' and Tab - you will see this again because
# `echo April' is in history:
$ echo April
# 2. now kill this line using C-k or C-u. C-r `April' doesn't work anymore
# because there is no `echo April' in the history
# 3. DON'T PRESS RETURN HERE! Press Up arrow first a couple of times and
# press Return to invoke a different command, it can be anything you had
# in your history but just no Return here
# 4. now, see `history', somewhere there you will see the empty string. It
# may look a bit different depending on your HISTTIMEFORMAT but note
# there is an asterisk next to the history line number and a command is
# missing. It's missing because it has been modified and saved in 2).
$ history
(...)
483* 2015-04-12 02:36:19
正如您在问题的第二条评论中注意到的那样,如果您在 2) 中按 Return 键,您将不会修改在点 0) 输入的原始命令,并且能够使用C-调用它r。
好吧,我意识到乍一看这可能会很令人困惑且难以理解。如果您有任何问题请回来,我会尽力说得更清楚。