如何從 BASH 中的歷史命令中刪除包含特定字串的所有條目?

如何從 BASH 中的歷史命令中刪除包含特定字串的所有條目?

有沒有任何命令或方法可以從 bash shell 的歷史記錄中刪除包含特定字串的所有條目?這對於刪除歷史記錄中包含密碼的命令很有用。我知道我們可以透過編號刪除每個歷史記錄條目,但問題是它一次只能刪除一個條目,而我每次都需要取出編號來刪除新條目。

例如。歷史命令顯示 5 個包含密碼 abcabc 的條目,我想從包含字串 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' '- 剪下第二列空格分隔的輸出,即行號
  • 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設為ignorebothor ignorespace。這將允許您輸入命令,bash並且如果它們以空格開頭,則不會將它們放入歷史記錄中:

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

$請注意和 命令之間的空格,這將使該行在 bash 歷史記錄中被忽略。

-i: 表示內聯編輯檔。
d最後意味著刪除包含之間表達式的行/

此解決方案僅適用於 Linux GNU sed

相關內容