
特定の文字列を含む bash シェルの履歴からすべてのエントリを削除するコマンドまたは方法はありますか? これは、パスワードを含む履歴内のコマンドを削除するのに役立ちます。各履歴エントリを番号で削除できることはわかっていますが、問題は、一度に 1 つのエントリしか削除されず、新しいエントリを削除するたびに番号を取り出す必要があることです。
例えば、履歴コマンドにはパスワード abcabc を含む 5 つのエントリが表示され、文字列 abcabc を含むすべてのエントリを履歴コマンドから削除したい場合
975 2019-03-15 11:20:30 ll
976 2019-03-15 11:20:33 ll cd
977 2019-03-15 11:20:36 ll CD
978 2019-03-15 11:20:45 chown test1:test1 CD
979 2019-03-15 11:20:53 chown test1:test1 ./CD
980 2019-03-15 11:20:57 chown test1:test1 .\CD
981 2019-03-15 11:22:04 cd /tmp/logs/
982 2019-06-07 10:36:33 su test1
983 2019-08-22 08:35:10 su user1
984 2019-08-22 08:35:15 /opt/abc/legacy.exe -password abcabc
985 2019-09-24 07:20:45 cd /opt/test1/v6r2017x
986 2019-09-24 07:20:46 ll
987 2019-09-24 07:21:18 cd /tmp/
988 2019-09-24 07:21:19 ll
989 2019-09-24 07:21:24 cd linux_a64/
990 2019-09-24 07:21:25 /opt/abc/legacy.exe -password abcabc
991 2019-09-24 07:24:03 cd build/
992 2019-09-24 07:24:04 ll
993 2019-09-24 07:24:07 cd ..
994 2019-09-24 07:24:10 /opt/abc/legacy.exe -password abcabc
995 2019-09-24 07:24:15 cd someapp/bin
996 2019-09-24 07:24:21 ll
997 2019-09-24 07:24:33 cd .
998 2019-09-24 07:24:35 cd ..
999 2019-09-24 07:24:36 ll
次のコマンドを試しましたが、以下のようなエラーが発生しました。
servername:~ # sed -i 'g/abcabc/d' /home/user1/.bash_history
sed: -e expression #1, char 2: extra characters after command
期待値: エラーはなく、文字列 abcabc を含むすべてのエントリが削除されるはずです。
答え1
@cprn の回答と似ていますが、awk
ではなくcut
と関数を使用しています。
function del_word_history () {
if [ -z "${1}" ]; then return false; fi
mapfile -t result <<< "$(history | grep "${1}" | tac | awk '{print $1}')"
for idx in "${result[@]}"; do
history -d $idx
done
}
tac
出力の行を反転します(一部の投稿では、すべてのシステムに共通ではないと指摘されています)[-z $1 ]
:true
関数に渡される最初の引数 ($1
) が空の場合。mapfile -t
(マニュアルページ;いくつかのガイド):stdin
配列変数に読み込みます (result
)"${result[@]}"
配列を返す
awk '{print $1}'
(GNU ユーザーガイド、簡単なガイド、マニュアルページ): 一致の識別と処理の両方に使用されます。空白で区切られたデータを分割し (デフォルト)、変数に格納します$n
。'{pring $1}'
読むprint
最初の単語に対してアクションを実行する。
使用法:
del_word_history history
del_word_history abcabc
history -w
以下はよりクリーンなソリューションこれは、複数行のエントリの他の単語ではなく、idx
の番号を取得したかどうかを確認します。history
function del_word_history () {
if [ -z "${1}" ]; then return false; fi
mapfile -t lines <<< "$(history | grep "${1}" | tac)"
for line in "${lines[@]}"; do
idx="$(printf '%s' "${line}" | awk '{ if ($1 ~ /^[0-9]+$/) { print $1 } }')"
if [ -n "${idx}" ]; then
echo "removing line ${idx}"
history -d $idx
fi
done
}
主な違いは次のとおりです。
- 配列変数の全行を取得する
lines
には、mapfile
awk '{ if ($1 ~ /^[0-9]+$/) { print $1 }}'
各行の最初の単語が数字であるかどうかをチェックし、それがstdout
同じ最初の単語であるかどうかを確認します(そして変数を取得しますidx
)。[ -n ${idx}" ] just checks if
idx` は空ではありません
答え2
古いことは承知していますが、次のようにループで実行しました。
for ln in $( history | grep my_phrase | cut -f2 -d' '); do
history -d $ln
done
$(...)
- コマンド置換、戻りstdout
値...
cut -f2 -d' '
- スペースで区切られた出力の2列目、つまり行番号をカットしますhistory -d $ln
- 履歴から指定された行番号を削除します
簡単にコピー&ペーストできるワンライナー:
for ln in $( history | grep my_phrase | cut -f2 -d' '); do history -d $ln; done
答え3
sed
を使用して からエントリを削除できます.bash_history
。
ただし、これは CLI でパスワードを再度入力するのを避けるためのパスワードなので.bashrc
、ファイルを編集して の行がまたはHISTCONTROL
に設定されていることを確認することをお勧めします。これにより、 にコマンドを入力して、スペースで始まる場合は履歴に残さなくなります。 ignoreboth
ignorespace
bash
promtpt:$ sed -i '/abcabc/d' /home/user/.bash_history
$
とコマンドの間にスペースがあることに注意してください。これにより、bash 履歴でその行が無視されます。
-i
: はファイルをインラインで編集することを意味します。
d
最後に、 の間にある式を含む行を削除することを意味します/
。
このソリューションは Linux でのみ機能しますGNU sed
。