改行を含む複数行の履歴エントリを保存するようにBashを設定しました。
shopt -s cmdhist lithist
export HISTTIMEFORMAT='%F %T '
シェルを終了すると、履歴に~/.bash_history
項目を区切るタイムスタンプが追加されます。たとえば、次のようになります。
#1501293767
foo() {
echo foo
}
#1501293785
ls
HISTIGNORE
いくつかのコマンドをフィルタリングするように設定してみました。
HISTIGNORE='ls[ ]*:man[ ]*:cat[ ]*'
しかしすぐに、私は現在のセッションの(メモリ内)レコードにすべてを含めることを好むことに気づきました。
~/.bash_logout
このフィルタ機能を活用したいと思います。これら 回答いくつかの関連質問)。
複数行エントリを使用すると、フィルタリングがより複雑になります。タイムスタンプの後の最初の行が無視できるパターンの1つと一致するものを識別し、タイムスタンプを含む項目全体を除外する必要があります。
私はawkを使ってこれを行う方法を見つけましたが、awkのスキルがそれほど良くないので、より良い方法があるかどうか疑問に思います。
filter_history() {
tmpfile=$(mktemp)
history -w $tmpfile
awk '/^#[[:digit:]]{10}$/ { timestamp=$0; ignore=0; next }
length(timestamp) > 0 && /^(ls|man|cat)([^[:alnum:]]|$)/ { timestamp=""; ignore=1 ; next }
length(timestamp) > 0 { print timestamp; timestamp=""; print; next }
ignore == 0 { print }' \
$tmpfile >> $HISTFILE && rm $tmpfile
}
編集する:実際には、複数行の項目をフィルタリングしたい状況は思い出されません。例えば、 で始まってもls
複数行にまたがっている場合は、おそらく興味深く覚えておく価値があることをしているでしょう。
ベストアンサー1
最初の行が「無視」パターンと一致していても、複数行の項目を維持する必要があるという要件により、少し複雑になります。私はHISTFILEがディスクに書き込まれた後、それをフィルタリングするためにAwkに有限ステートマシンを作成しました(書き込まれる前にフィルタリングをトリガーする方法が見つかりませんでした)。
~/.bashrc:
# if shell is interactive, filter history upon exit
if [[ $- == *i* ]]; then
trap '$HOME/.bash_history_filter >/dev/null 2>&1 &' EXIT
fi
~/.bash_history_filter:
tmpfile=$(mktemp)
trap 'rm -f "$tmpfile"' EXIT
filter_script="$HOME/.bash_history_filter.awk"
persisted_history="${HISTFILE:-$HOME/.bash_history}"
if [[ -r "$filter_script" && -r "$persisted_history" ]]; then
awk -f "$filter_script" "$persisted_history" > "$tmpfile"
mv "$tmpfile" "$persisted_history"
fi
~/.bash_history_filter.awk:
/^#[[:digit:]]{10}$/ {
timestamp = $0
histentry = ""
next
}
$1 ~ /^(ls?|man|cat)$/ {
if (! timestamp) {
print
} else {
histentry = $0
}
next
}
timestamp {
print timestamp
timestamp = ""
}
histentry {
print histentry
histentry = ""
}
{ print }
いくつかの関連投稿(ここそしてここ)これはsedを使用して行うことができると思われます。まだ調べていませんが、比較してどうか知りたいです。