在shell中更改增量搜索的方向
1. 概述
shell 程序的一个重要功能是将用户以前的命令保留为历史记录。在本文中,我们将研究 GNU Bash 提供的搜索功能,并了解终端和 shell 使用的冲突键序列 ( Cs )。
2.增量搜索
GNU Bash shell 通过Readline 库 提供命令行编辑功能。这个库包括几个历史搜索函数,reverse-history-search和forward-history-search,它们分别绑定到Cr和Cs键序列。
我们可以通过使用bash中的内置命令 bind来确认这一点:
bind -q reverse-search-history;
# reverse-search-history can be invoked via "\C-r".
bind -q forward-search-history;
# forward-search-history can be invoked via "\C-s".
这些搜索功能可用于获取较早的命令并将其恢复到当前行。它们还具有对每个角色输入的即时反馈。这称为增量搜索。
让我们在 bash 中创建一些 shell 历史数据并演示一个简单的搜索体验:
unset HISTFILE # if variable HISTFILE is unset, then ~/.bash_history will not be modified.
history -c
: a;
: b;
: c;
: d;
: e;
现在,让我们搜索命令 ’ : e; ‘在我们的历史中。为此,我们只需输入键序列Cr以调用搜索功能并输入字符“ e ”:
(reverse-i-search)`e': : e;
bash 的增量搜索有一个小问题:它保留其在历史列表中的位置,并且在搜索失败后不会换行。当我们在历史列表中的较早位置尝试搜索命令时,可以观察到这种行为:
(reverse-i-search)`d': : d;
(failed reverse-i-search)`e': : d;
为了找到’ :e;’ 在不完全重新开始搜索的情况下,我们需要使用Cs键序列调用函数forward-history-search 。不幸的是,Cs很可能在 shell 收到它之前就被拦截和消耗掉了。 我们将在下一节中了解另一个也使用键序列Cs的系统,但现在,我们应该通过发送键序列Cg来中止搜索。
2. 软件控制流程(XOFF/XON)
历史上,Cs和Cq用于在两个系统之间传递控制代码XOFF和XON 。在基于终端的系统中,这些控制代码用于暂停正在向终端传输数据的进程。
让我们打开一个 shell 并观察Cs和Cq可用于停止/恢复循环构造,因为循环体请求将数据写入终端:
for i in 1 2 3 4 5; do
printf "%s\n" $i; sleep 1;
done;
幸运的是,可以将键序列Cs从发送控制代码XOFF中解放出来,让键序列成功到达 shell。stty实用程序 可用于配置输入设置ixon,从而启用XOFF/XON流控制。在禁用ixon之前,让我们先确认当前设置:
stty -a | grep "ixon"
# -ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff
# ^^^^
stty -ixon
stty -a | grep "ixon"
# -ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl -ixon -ixoff
# ^^^^^
键序列Cs现在应该成功调用 bash shell 的forward-search-history函数:
(i-search)`':
但是,这些设置不会持续存在。我们需要为每个新的 shell 会话配置它们。为了保持这些设置,我们必须在 shell 的启动文件中包含命令stty -ixon。
3. 切换搜索方向
当我们调用forward-search-history函数时,搜索从当前位置开始,这实际上是历史列表中的最后一个位置。因此,使用forward-search-history作为reverse-search-history功能的补充更为相关,它 在搜索时有效地向后移动搜索位置。
让我们为命令历史创建一个新数据集,以演示forward-search-history的典型用法:
unset HISTFILE # if variable HISTFILE is unset, then ~/.bash_history will not be modified.
history -c
: a;
: b;
: x1;
: d;
: x2;
: e;
现在,让我们搜索命令 ’ : x1; ’ 我们之前跑过的那个。我们可以通过简单地输入键序列Cr来调用搜索功能并输入字符“ x1 ”来做到这一点:
(reverse-i-search)`x1': : x1;
假设我们要继续搜索,但要搜索稍后运行的命令。我们可以简单地输入键序列Cs来改变搜索的方向,然后更正搜索词:
(i-search)`x2': : x2;
最后,我们可以通过发送ESC键或键序列Cj来终止搜索并将搜索结果插入当前行。