web-dev-qa-db-ja.com

.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コマンドは実際には2回記録されます。私は定期的にw/cronを実行することを考えました:

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

これで重複を削除できますが、残念ながら順序は保持されません。私がファイルをsortしないと、最初にuniqが適切に動作するとは思えません。

.bash_historyの重複を削除して順序を維持するにはどうすればよいですか?

追加クレジット:

スクリプトによる.bash_historyファイルの上書きに問題はありますか?たとえば、Apacheログファイルを削除した場合、killでNohup /リセット信号を送信して、ファイルへの接続をフラッシュする必要があると思います。 .bash_historyファイルの場合、おそらくpsを使用して、フィルタリングスクリプトが実行される前に接続されたセッションがないことを確認してください。

69
cwd

履歴を並べ替える

このコマンドはsort|uniqと同じように機能しますが、行はそのままです。

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

基本的に、各行にその番号を付加します。 sort|uniq- ingの後、すべての行は元の順序に従って(行番号フィールドを使用して)並べ替えられ、行番号フィールドは行から削除されます。

このソリューションには、等値線のクラスのどの代表がそれを出力に含めるかが定義されていないため、最終出力での位置が定義されていないという欠点があります。ただし、最新の担当者を選択する必要がある場合は、2番目のキーで入力をsortできます。

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

.bash_historyの管理

履歴の再読み取りと書き戻しには、それぞれhistory -ahistory -wを使用できます。

37
artistoex

だから私は重複に悩まされた後に同じ正確なものを探していました、そして私が〜/ .bash_profile(Mac)を編集すると:

export HISTCONTROL=ignoreboth:erasedups

それはあなたが望むものを正確に行います、それはどんなコマンドの最新のものも保持します。 ignorebothは実際にはignorespace:ignoredupserasedupsを併用すると、作業が完了します。

少なくとも私のbashを搭載したMac端末では、この作業は完璧です。見つけた ここaskubuntu.comに

57
sprite

このソリューションを実際に見つけてテストしました:

awk '!x[$0]++'

線の特定の値($ 0)が初めて表示されるとき、x [$ 0]の値はゼロです。
ゼロの値は!で反転され、1になります。
評価が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.
21
Clayton Stanley

クレイトンアンサーの拡張:

tac $HISTFILE | awk '!x[$0]++' | tac | sponge $HISTFILE

tacファイルを元に戻します。moreutilsがインストールされていることを確認し、spongeを使用できるようにします。そうでない場合は、一時ファイルを使用します。

12
Ali Shakiba

これは古い投稿ですが、複数の端末を開いて、履歴をウィンドウ間で同期させたいが重複はさせたくないユーザーにとっては、永続的な問題です。

.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に保存されるのを防ぎます
  • Promptコマンドは履歴キャッシュを更新します
    • history -nは、最後のキャリッジリターン以降に別の端末で発生した可能性がある$ HISTFILEからすべての行を読み取ります
    • history -w更新されたバッファを$ HISTFILEに書き込みます
    • history -cバッファをワイプして、重複が発生しないようにします
    • history -r $ HISTFILEを再度読み取り、現在は空のバッファに追加します
  • awkスクリプトは、遭遇した各行の最初の出現を保存します。 tacはそれを元に戻し、次に元に戻します。これにより、履歴内でまだ最新の最新のコマンドで保存できます。
  • / tmpファイルのrm

新しいシェルを開くたびに、すべての重複が消去されます。 Enter 別のシェル/ターミナルウィンドウでキーを押すと、この履歴がファイルから更新されます。

7
smilingfrog

これらは最後に複製された行を保持します:

Ruby -i -e 'puts readlines.reverse.uniq.reverse' ~/.bash_history
tac ~/.bash_history | awk '!a[$0]++' | tac > t; mv t ~/.bash_history
6
Lri

すべての新しいコマンドを一意に記録するのは難しいです。まず、~/.profileまたは同様のものに追加する必要があります。

HISTCONTROL=erasedups
Prompt_COMMAND='history -w'

次に、~/.bash_logoutに追加する必要があります。

history -a
history -w
0
Steven Penny