![如何在交互式 shell 中合并重复的命令历史记录?](https://linux22.com/image/60906/%E5%A6%82%E4%BD%95%E5%9C%A8%E4%BA%A4%E4%BA%92%E5%BC%8F%20shell%20%E4%B8%AD%E5%90%88%E5%B9%B6%E9%87%8D%E5%A4%8D%E7%9A%84%E5%91%BD%E4%BB%A4%E5%8E%86%E5%8F%B2%E8%AE%B0%E5%BD%95%EF%BC%9F.png)
当您尝试通过 查找交互式 shell 会话中以前使用过的命令时 ↑ (up arrow),您可能会得到类似的信息
$ls # 1st time push `up arrow`
$ls # 2nd time push `up arrow`
$ls # 3rd time push `up arrow`
$ls # 4th time push `up arrow`
$ls # 5th time push `up arrow`
$ls # 6th time push `up arrow`
$make # 7th time push `up arrow`
$make # 8th time push `up arrow`
$make # 9th time push `up arrow`
$ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" # Bingo!
如果是这样的话我会更好:
$ls # 1st time push `up arrow`
$make # 2th time push `up arrow`
$ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" # Bingo!
因为重复的历史记录通常是没有用的。
我怎样才能让 Bash 做到这一点?
答案1
ignoredups
您可以通过设置HISTCONTROL 变量来完成此操作:
HISTCONTROL="ignoredups"
可选择导出它,
export HISTCONTROL="ignoredups"
使其成为环境变量。来自bash(1) 手册页:
HISTCONTROL
以冒号分隔的值列表,控制命令如何保存在历史列表中。如果值列表包含
ignorespace
, 以 a 开头的行空间字符不保存在历史列表中。值ignoredups
会导致与先前历史记录条目匹配的行不被保存。的值ignoreboth
是ignorespace
和 的 简写ignoredups
。值erasedups
会导致与当前行匹配的所有先前行在保存该行之前从历史记录列表中删除。任何不在上面列表中的值都将被忽略。如果HISTCONTROL
未设置,或者不包含有效值,则 shell 解析器读取的所有行都会保存在历史列表中,具体取决于以下值HISTIGNORE
。多行复合命令的第二行和后续行不进行测试,并且无论 的值如何,都会添加到历史记录中HISTCONTROL
。
这确实确切地问题要求什么。如果用户输入命令ruby …
,
make
, make
, make
, ls
, ls
, ls
, ls
,ls
和 ls
(作为单独的连续行),则历史列表将为ruby …
, make
, ls
。按 ↑ (up arrow)三下将返回到 ruby
命令。
答案2
要添加到 @jordanm 回复,我认为您实际上应该使用 HISTCONTROL 但使用“擦除”价值。
“erasedups 值会导致与当前行匹配的所有先前行在保存该行之前从历史列表中删除。”
export HISTCONTROL="ignoreboth:erasedups"
将其添加到您的文件中,~/.bashrc
以便在您每次登录时执行。
其实这已经是回答了前
我想添加评论,但由于我的声誉而无法添加评论。
答案3
对于 Macos,将以下行添加到文件中~/.zshrc
以避免终端历史记录中出现命令重复
setopt HIST_EXPIRE_DUPS_FIRST
setopt HIST_IGNORE_DUPS
setopt HIST_IGNORE_ALL_DUPS
setopt HIST_IGNORE_SPACE
setopt HIST_FIND_NO_DUPS
setopt HIST_SAVE_NO_DUPS
答案4
我真的找不到任何有用的东西!
我创建了一个在启动时运行的 bash 文件,但您也可以使用 cron 来安排它。它从 .bash_history 中删除重复的内容。
arrVar=()
while read -r line; do
s=${line# } # remove leading spaces
s=${line%% } # remove trailing spaces
if [[ ! " ${arrVar[*]} " =~ " ${s} " ]] && [[ "$s" != history* ]] ;
then
arrVar+=("$s")
fi
done < ~/.bash_history
printf "%s\n" "${arrVar[@]}" > ~/.bash_history