我的 bash 环境处于 vi 模式 ( set -o vi
)。所以我可以输入<ESC>/
一个单词,然后回车,然后 bash 在历史记录中搜索该单词。由于/
这也是 vi 搜索正则表达式的方法,因此我认为 bash 也会搜索正则表达式。
不幸的是,当我输入<ESC>/foo.*bar
bash 时,它在历史记录中找不到任何与正则表达式匹配的行foo.*bar
。
我是否忽略了某些事情,或者是否无法在历史记录中搜索正则表达式?
答案1
简短的回答是你可以不是使用正则表达式搜索 shell 历史记录。根据POSIX(类 Unix 操作系统的标准),您应该能够使用常规搜索shell 模式匹配(用于文件名通配和case
语句)。此功能称为非增量搜索但目前它似乎没有在 Bash 中正确实现。
POSIX规范
shell 的 POSIX 规范命令行编辑(vi 模式)指出这些搜索模式应使用常规 shell 模式匹配。虽然^
元字符用于匹配行的开头,但它们是不是常用表达。
/pattern<newline>
从上一个命令行开始,向后浏览命令历史记录,搜索指定的模式。模式使用中描述的模式匹配符号模式匹配表示法 ,但“^”字符作为第一个字符出现时应具有特殊含义图案。在这种情况下,“^”将被丢弃,“^”之后的字符仅在行首匹配。命令历史记录中的命令应被视为字符串,而不是文件名。
记录 Bash 实施
Bash 使用GNU 阅读线库提供交互式行编辑和历史搜索功能。 Readline 库的官方文档更多地关注 Emacs 模式,但其手册中有一小部分,Readline vi 模式指出
虽然 Readline 库没有全套 vi 编辑功能,但它确实包含足够的功能来允许对行进行简单的编辑。
Readline vi 模式的行为符合 POSIX 标准中的指定。
实际的 Bash 实施
经过在两个不同系统上的多次实验,我发现 Bash/Readline 中的非增量搜索并不像其官方文档中描述的那样工作。我发现 被*
视为字面星号而不是匹配多个字符的模式。同样,?
和[
也被视为文字字符。
为了进行比较,我尝试使用 Vi-modetcsh
并验证它是否正确实现了 POSIX 标准中指定的历史搜索。
然后,我下载并搜索了 Readline 库的代码,发现它的历史搜索功能使用简单的子字符串搜索,并且不使用任何搜索模式元字符 - 除了插入符号之外,^
(请参阅搜索.c来自 Readline 库的 git 存储库)。
我认为 Bash/Readline 开发人员尚未实现此功能。我找不到错误列表,但CHANGES
文件显示他们一直在定期修复与 Vi 模式相关的问题。
更新:该功能在 Readline 8.0 中实现(2019 年 1 月与 Bash 5.0 一起发布)。正如其记录的变化:
Readline 的新功能
A。非增量 vi 模式搜索 (
N
,n
) 可以搜索 shell 模式,如 Posix 指定的那样(fnmatch(3)
如果可用则使用)。