如何删除 .bash_history 中的重复项并保持顺序?

如何删除 .bash_history 中的重复项并保持顺序?

我真的很喜欢使用control+r递归搜索我的命令历史记录。我发现了一些我喜欢使用的好选项:

# ignore duplicate commands, ignore commands starting with a space
export HISTCONTROL=erasedups:ignorespace

# keep the last 5000 entries
export HISTSIZE=5000

# append to the history instead of overwriting (good for multiple connections)
shopt -s histappend

对我来说唯一的问题是erasedups只删除连续的重复项 - 因此使用这串命令:

ls
cd ~
ls

ls命令实际上会被记录两次。我考虑过定期运行 cron:

cat .bash_history | sort | uniq > temp.txt
mv temp.txt .bash_history

这将实现删除重复项,但不幸的是顺序不会被保留。如果我不sort先使用该文件,我相信无法uniq正常工作。

如何删除 .bash_history 中的重复项并保持顺序?

额外学分:

.bash_history通过脚本覆盖文件有什么问题吗?例如,如果您删除 apache 日志文件,我认为您需要发送 nohup / Reset 信号以kill使其刷新与文件的连接。如果文件就是这种情况.bash_history,也许我可以以某种方式用来ps检查并确保在运行过滤脚本之前没有连接的会话?

答案1

因此,在对重复项感到恼火后,我一直在寻找完全相同的东西,并发现如果我用以下内容编辑 my~/.bash_profile或 my ~/.bashrc

export HISTCONTROL=ignoreboth:erasedups

它几乎完全符合您的要求,它只在一个 shell 实例中保留最新的任何命令。ignoreboth实际上就像做事一样ignorespace:ignoredups,并且erasedups完成工作。

至少在我的 Mac 终端上,bash 可以完美地工作。找到了请访问 askubuntu.com

请注意,这ignoredups无助于从现有.bash_history.使用 时,重复项仍会出现在文件中shopt -s histappend

答案2

对历史进行排序

该命令的工作方式与 类似sort|uniq,但将线条保持在适当的位置

nl|sort -k 2|uniq -f 1|sort -n|cut -f 2

基本上,在每行前面添加其编号。 -ing之后sort|uniq,所有行将根据其原始顺序(使用行号字段)重新排序,并且行号字段将从行中删除。

该解决方案的缺陷在于,未定义一类相等线的哪个代表将出现在输出中,因此其在最终输出中的位置未定义。但是,如果应选择最新的代表,您可以sort通过第二个键输入:

nl|sort -k2 -k 1,1nr|uniq -f1|sort -n|cut -f2

管理.bash_history

要重新读取和写回历史记录,可以分别使用history -a和。history -w

答案3

在野外找到了这个解决方案并进行了测试:

awk '!x[$0]++'

第一次看到某行的特定值 ($0) 时,x[$0] 的值为零。
零值反转!并变为一。
计算结果为 1 的语句会导致默认操作,即打印。

因此,第一次$0看到某个特定内容时,它会被打印出来。

每次下一次(重复) 的值x[$0]都会增加,
其负值为零,并且不会打印计算结果为零的语句。

要保留最后的重复值,请反转历史记录并使用相同的 awk:

awk '!x[$0]++' ~/.bash_history                 # keep the first value repeated.

tac ~/.bash_history | awk '!x[$0]++' | tac     # keep the last.

答案4

这是一篇旧文章,但对于想要打开多个终端并在窗口之间同步历史记录但不重复的用户来说,这是一个永久的问题。

我在 .bashrc 中的解决方案:

shopt -s histappend
export HISTCONTROL=ignoreboth:erasedups
export PROMPT_COMMAND="history -n; history -w; history -c; history -r"
tac "$HISTFILE" | awk '!x[$0]++' > /tmp/tmpfile  &&
                tac /tmp/tmpfile > "$HISTFILE"
rm /tmp/tmpfile
  • histappend 选项将缓冲区的历史记录添加到历史记录文件 ($HISTFILE) 的末尾
  • ignoreboth 和 Erasedups 防止重复条目保存在 $HISTFILE 中
  • 提示命令更新历史缓存
    • history -n从 $HISTFILE 中读取自上次回车以来可能在不同终端中出现的所有行
    • history -w将更新的缓冲区写入 $HISTFILE
    • history -c擦除缓冲区,这样就不会发生重复
    • history -r重新读取 $HISTFILE,附加到现在空白的缓冲区
  • awk 脚本存储它遇到的每一行的第一次出现。tac反转它,然后将其反转回来,以便可以使用历史记录中最新的命令来保存它
  • rm /tmp 文件

每次你打开一个新的 shell 时,历史记录都会被擦除,每次你Enter在不同的 shell/终端窗口中按下按键时,它都会从文件中更新此历史记录。

相关内容