如何在 vi 模式下搜索 bash 历史记录中的“foo.*bar”

如何在 vi 模式下搜索 bash 历史记录中的“foo.*bar”

我的 bash 环境处于 vi 模式 ( set -o vi)。所以我可以输入<ESC>/一个单词,然后回车,然后 bash 在历史记录中搜索该单词。由于/这也是 vi 搜索正则表达式的方法,因此我认为 bash 也会搜索正则表达式。

不幸的是,当我输入<ESC>/foo.*barbash 时,它在历史记录中找不到任何与正则表达式匹配的行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)如果可用则使用)。

相关内容