bashシェル履歴から特定の文字列を含むすべてのエントリを削除するコマンドまたは方法はありますか?これは、履歴からパスワードを含むコマンドを削除するのに役立ちます。各履歴項目を番号で削除できることはわかっていますが、問題は一度に1つの項目のみを削除し、新しい項目を削除するには毎回番号を削除する必要があることです。
例えば。 Historyコマンドには、パスワード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
。