我有无限的.zsh_history
,目前是 10k 行。我经常想查看历史记录中具有特定字符串的所有命令,例如curl
.如果我history | grep curl
这样做,需要很长时间才能完成。如果我grep curl ~/.zsh_history
这样做,速度会快得多,但格式会被破坏(时间戳不会解析为日期,分隔符会保留为符号)。
有没有办法解决管道传输缓慢的history
问题grep
?我看到人们推荐 Ctrl+R 但这显然不是同一件事 - grep 产生一个列表命令,而 Ctrl+R 每次显示一个命令。此外,管道到 grep 允许链接多个 grep 过滤器,而使用 Ctrl+R 则无法实现相同的操作。
答案1
首先,如果您没有做任何比 grep 更复杂的事情,则限制匹配history -m PATTERN
可能比 grep 更快。即使您之后应用复杂的过滤器,也可以尝试添加一个简单的过滤器,以-m
消除大多数不需要的线条。
如果限制因素是使用 打印完整历史记录所花费的时间history
,则有一种黑客方法可以打印 grep (或其他过滤器)选择的历史记录部分。使用fc -p
开始一个新的历史记录,并使其读取历史记录的选定部分。未经测试:
function format_history {
fc -p -a =(cat)
fc -l 1
}
history 1 | grep curl | format_history
这使用起来不太方便(管道两边都需要一些东西,所以不能只有前缀magic_history_filter
)。它在不格式化整个历史记录时获得的速度,可能会因拥有更高级的管道和需要使用临时文件而损失(zsh 只能从可查找文件中读取历史记录,而不是从管道中读取历史记录)。
答案2
这是一个简单的函数,可让您快速搜索整个历史记录中的任何字符串:
histgrep() {
fc -lm "*${1}*" 1 -1
}
甚至更快:
histgrep() {
zmodload -i zsh/parameter
print -raC2 ${(kv)history[(R)*$1*]}
}
其中任何一个都会在每行前面输出一个历史行号,因此您可以使用 执行所需的行!<number>
。例如,要将历史行号 2596 插入命令行中,请执行以下操作
!2596
然后按Tab或Enter。
我有大约 3400 行历史记录。对我来说,这样做histgrep cd
会产生超过 220 行代码,但第一个版本的函数只需要大约 0.004 秒即可完成,而第二个版本只需大约 0.004 秒即可完成。
答案3
有时你可以跑步history >~/.zsh_history.cache
。然后,您可以 grep 该文件以及history
该文件中缺少的那些命令的输出。
我不熟悉zsh
,因此无法提供将文件内容与命令输出相结合的代码。
答案4
你可以尝试 ripgrep (https://github.com/BurntSushi/ripgrep)实际上更快,并且有许多有用的过滤选项:github 页面有很长的功能列表。
它位于许多发行版的存储库中。