BASHのコマンド履歴から特定の文字列を含むすべてのエントリを削除する方法は?

BASHのコマンド履歴から特定の文字列を含むすべてのエントリを削除する方法は?

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 ifidx`が空ではありません

答え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することをお勧めします。これによりコマンドを入力でき、スペースで始まる場合は履歴に入力されません。 ignorebothignorespacebash

promtpt:$ sed -i '/abcabc/d' /home/user/.bash_history

$とコマンドの間のスペースに注意してください。これは bash レコードの対応する行を無視します。

-i:ファイルをインラインで編集することを意味します。
d最後は、間に式を含む行を削除することを意味します/

このソリューションはLinuxでのみ機能しますGNU sed

関連情報