Bash历史记录搜索,部分匹配+向上箭头

我已经搜索过了,但没有找到任何相关的信息。我正在寻找一种在终端中使用 bash 的功能。

很久以前,我在一个 Debian 系统上有一个用户,一个朋友帮我设置了一个方便的历史记录搜索功能(我相信那时我使用的是 tcsh),我可以输入前一个命令的开头部分,按上箭头键,它就会根据部分字符串进行搜索。

例如,如果我的历史记录是:

./script.pl
./script.pl arg1
cat output
cat output | grep yada

我输入.,然后按上箭头,它会显示:./script.pl arg1。再次按下箭头,它会显示./script.pl,以此类推。
这很像在.bash_history上执行grep的功能。有没有办法获得这个功能?

1可能是 iPython Like Command History For Shell 的重复问题。 - Marcel Stimberg
1@Marcel 看起来可能是同样的答案,我在搜索中看到了这个,但没有将它与我的问题联系起来,包括iPython和Shell关键词。 - TLP
听起来像这样-https://github.com/zsh-users/zsh-autosuggestions。 - slm
7个回答

创建~/.inputrc文件并添加以下内容:
# Respect default shortcuts.
$include /etc/inputrc

## arrow up
"\e[A":history-search-backward
## arrow down
"\e[B":history-search-forward

提示:请阅读底部的$include /etc/inputrc的解释,或者如果您已经有文件~/.inputrc,则该怎么做。

#开头的行是注释。

我记不清什么是向后和向前了。试着实验一下。也许你需要交换向后和向前。

关闭并重新打开所有终端,以使新行为生效。


一些背景信息:
Bash使用readline来处理提示符。 ~/.inputrc是readline的配置文件。请注意,这也会影响其他使用readline库的软件,例如IPython
阅读bash手册以获取有关readline的更多信息。在那里,您还可以找到更多与历史记录相关的readline命令history related readline commands
要获取箭头键的转义码,可以按照以下步骤进行操作:
  1. 在终端中启动cat(只需输入cat,无需其他参数)。
  2. 在键盘上键入键,您将得到类似于^[[A表示向上箭头和^[[B表示向下箭头的内容。
  3. ^[替换为\e
有关^[\e的更多信息,请参见此处:https://unix.stackexchange.com/a/89817/380515
关于行$include /etc/inputrc
Readline尝试读取~/.inputrc进行配置。如果该文件不存在,它将尝试读取/etc/inputrc。这意味着如果~/.inputrc存在,它将不会读取/etc/inputrc
一些发行版在/etc/inputrc中准备了一些配置。如果您创建了~/.inputrc,则会丢失预先准备的配置。这可能是您想要的,也可能不是。为了仍然保留/etc/inputrc中的预先准备配置,您可以在~/.inputrc中使用行$include /etc/inputrc
如果您已经有了~/.inputrc文件,这意味着您要么已经知道自己在做什么,要么是从设置您系统的人那里继承下来的,或者之前遵循了其他指南告诉您创建该文件并忘记了。无论如何,您可能希望检查/etc/inputrc并决定是否要保留它与行$include /etc/inputrc

4很好,但是这个解决方案会禁用ctrl-left/ctrl-right的快捷键。 - Eyal
有人能告诉我如何实现相同的效果吗? - Hitesh Kumar
我会单独给猫部分加分的,@lesmana。 - Mike D
同意 @Eyal 的观点,有人能给我一些建议吗?我想保留 ctrl-left/ctrl-right 快捷键,但又想实现这个功能。 - kbrose
弄清楚了,不知怎么回事,readline 一定是在 .inputrc 文件不存在时推断出了一些默认值,但是当检测到该文件后,这些默认值就被去掉了。除了答案中提供的快捷键之外,还要添加几行代码来保留 ctrl-left/ctrl-right 快捷键:例如 "\e[1;5C":forward-word"\e[1;5D":backward-word - kbrose
11为了保留所有默认设置,请在首行添加$include /etc/inputrc - Tulio Casagrande
@Eyal,在这个链接中修复问题:如何修复Ctrl+左箭头不跳过单词的问题。同时,您还可以查看这个链接了解更多信息:为什么Ctrl+左箭头不能跳过单词? - αғsнιη
有没有什么原因导致在bash中执行某些命令后,这种行为会出现问题?我需要另一个bash才能使其再次正常工作。 - dashesy
这只是在我的shell中写入~符号。 - Soren
除了上面的答案之外,你可以在这里找到所有的关键代码: https://en.wikipedia.org/wiki/ANSI_escape_code - Yohai Devir
我在现有的/etc/inputrc文件中删除了关于"\e[5"和"\e[6"这两行的注释。 - Tinashe Chinyanga

在/etc/profile.d/中创建一个名为setup_readline.sh的文件,权限设置为644,并包含以下内容。登录并检查您首选的按键:
bind '"\e[A": history-search-backward'
bind '"\e[B": history-search-forward'

我认为这是做这件事的最佳方式。尤其是如果您使用配置管理系统,如Chef、Puppet等

而且系统配置仍然未经触碰!


6奇怪的是,~/inputrc 对我没有起作用 - 但将这些命令放入 .bash_profile 中就可以了。 - Joe
1.inputrc在我的主文件夹中不存在,而且我更喜欢将这些设置放在.bashrc中,这样我只需要携带一个文件来保存我的设置。所以这可能是一个比被接受的答案更好的选择。 - Shital Shah
.inputrc 对我来说非常好用,但在加载 screen 后就不起作用了。奇怪的是,其他 .inputrc 的快捷键可以正常工作,但这些却不行。所以现在我同时使用两种解决方案。 - Orwellophile
1当你登录服务器并且需要执行一些操作时,这个功能非常有帮助。如果你在服务器上缺少这些功能,并且不想编辑和重新加载 ~/.inputrc 文件,那么这个功能就非常方便了。 - danmactough
如果你移除bind关键字和单引号',你应该可以把这些放在~/.inputrc文件中。 - joeytwiddle

按下 Ctrl + R 就能获得这种功能。开始输入部分命令,它会显示以前的命令,你可以用上下箭头进行导航。
更多信息请点击这里

2谢谢您的回复。是的,我尝试过那个方法,但我觉得有点... 麻烦。它不允许我滚动查看以部分字符开头的命令,只显示第一个。而且它会在整个命令中搜索该字符,这有点无用。 - TLP
7@TLP,请重复按下 Ctrl+r - akostadinov
默认情况下,ctrl+R不能实现上下箭头的功能。你只能重复使用ctrl+R来进行"向上搜索"。没有"向下搜索"的选项。 - wisbucky
@wisbucky,有一个叫做“search down”的功能;不幸的是,默认情况下它是不可用的。使用stty -ixon命令可以“启用”它。 - Maryan

以下解决方案结合并扩展了上述提到的一些方法: 将以下行添加到您的~/.bash_aliases文件(无需~/.inputrc),以实现以下行为:
  1. 通过按下CTRL+UP和CTRL+DOWN在历史记录中向上/向下移动(仅限具有相同前缀的条目)。这可以与仅使用UP和DOWN在完整历史记录中向上/向下移动的标准功能共存
  2. 通过按下CTRL+RIGHT和CTRL+LEFT在命令行中跳转到下一个/上一个单词
bind '"\e[1;5A":history-search-backward'
bind '"\e[1;5B":history-search-forward'
bind '"\e[1;5C":forward-word'
bind '"\e[1;5D":backward-word'

重新登录到shell(或运行source ./bash_aliases)以应用更改。

1嗨,你知道在哪里可以了解如何创建更复杂的键盘快捷方式吗?也许这种符号叫什么之类的? - Ekanshdeep Gupta
1相关术语包括"keycode"或"scancode"(我不是专家)。然而,实用的解决方案是:运行showkey -a会给出有用的输出,例如"^[[1;5A",它表示"\e[1;5A",即前导的"^["似乎指的是"\e"。 - cubic lettuce
第二点似乎是默认的,但对我来说不起作用 - 必须删除1;5 - xeruf

关于lesmana的回答,我应该在我的Trusty 14.04下创建~/.inputrc文件,并在~/.bashrc中进行验证/添加(我的~/.bashrc已经存在第一行)。
shopt -s histappend  
PROMPT_COMMAND='history -a'  

这已经在法语中解释这里


4这个命令基本上是指示bash立即将命令追加到历史文件中,而不是等待会话结束。如果您有很多终端打开,并且不想在其中一个终端中丢失历史记录,那么这个命令就很有用了,否则并不必要。https://www.digitalocean.com/community/tutorials/how-to-use-bash-history-commands-and-expansions-on-a-linux-vps - Shital Shah

也许你想试试https://github.com/dvorka/hstr,它提供了基于指标(命令的使用时间、频率和长度)的简单多行过滤Bash历史记录的功能 - 你可以使用箭头键轻松浏览历史记录。

enter image description here

可以很容易地将其绑定到Ctrl-r和/或Ctrl-s

有一种替代方法与@lesmana上面提到的类似,但您不必创建新的.inputrc文件。

相反,如果您拥有sudo权限,则可以在/etc/inputrc文件中启用此功能。该文件包含各种键盘设置,包括历史记录搜索功能(至少适用于18.04)。/etc/inputrc的摘录如下:

# alternate mappings for "page up" and "page down" to search the history
# "\e[5~": history-search-backward
# "\e[6~": history-search-forward

取消注释底部两行,使用sudo文件编辑器(例如$ sudo vim),新的终端会话将具有历史搜索功能(适用于所有用户)。这样,您就不必担心创建~/.inputrc文件,也不必添加$include语句,如@Tulio Casagrande在评论中提到的以保留ctrl-arrow输入。

1好主意,但你还需要将"\e[5"改为"\e[A",将"\e[6"改为"\e[B",否则它不会起作用。 - user587469