Wie entferne ich alle Einträge, die eine bestimmte Zeichenfolge enthalten, aus dem Verlaufsbefehl in BASH?

Wie entferne ich alle Einträge, die eine bestimmte Zeichenfolge enthalten, aus dem Verlaufsbefehl in BASH?

Gibt es einen Befehl oder eine Möglichkeit, alle Einträge aus dem Verlauf der Bash-Shell zu entfernen, die eine bestimmte Zeichenfolge enthalten? Dies ist nützlich, um Befehle aus dem Verlauf zu entfernen, die ein Passwort enthalten. Ich weiß, dass wir jeden Verlaufseintrag anhand seiner Nummer entfernen können, aber das Problem ist, dass immer nur ein Eintrag auf einmal gelöscht wird und ich jedes Mal die Nummer entfernen muss, um einen neuen Eintrag zu entfernen.

Beispiel: Der Befehl „History“ zeigt 5 Einträge mit dem Passwort abcabc und ich möchte alle Einträge aus dem Befehl „History“ entfernen, die die Zeichenfolge abcabc enthalten

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

Habe den folgenden Befehl versucht, der den folgenden Fehler ergab

servername:~ # sed -i 'g/abcabc/d' /home/user1/.bash_history
sed: -e expression #1, char 2: extra characters after command

Erwartung: Kein Fehler und alle Einträge, die die Zeichenfolge abcabc enthalten, sollten entfernt werden.

Antwort1

Eine weitere, die der Antwort von @cprn ähnelt, aber awk(anstatt cut) und eine Funktion verwendet:

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
}
  • tacinvertiert die Zeilen der Ausgabe (einige Beiträge wiesen darauf hin, dass dies nicht bei allen Systemen der Fall ist)
  • [-z $1 ]: truewenn das erste an die Funktion () übergebene Argument $1leer ist.
  • mapfile -t(manpage;einige Führer): liest stdinin eine Array-Variable ( result)
    • "${result[@]}"gibt das Array zurück
  • awk '{print $1}'(GNU-Benutzerhandbuch,Kurzanleitungen,manpage): wird sowohl für die Erkennung einer Übereinstimmung als auch für deren Verarbeitung verwendet. Es teilt die durch Leerzeichen getrennten Daten (Standard) auf und speichert sie in den $nVariablen.
  • '{pring $1}'liest fürführe printeine Aktion für das erste Wort aus.

Verwendung:

del_word_history history
del_word_history abcabc
history -w

Das Folgende ist einsauberere Lösungdas prüft, ob wir die idxNummer des erhalten haben historyund nicht ein anderes Wort eines mehrzeiligen Eintrags:

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
}

Die Hauptunterschiede sind:

  • erhalten wir die vollständigen Zeilen in der Array-Variable linesübermapfile
  • awk '{ if ($1 ~ /^[0-9]+$/) { print $1 }}'prüft, ob das erste Wort jeder Zeile eine Zahl ist und ob es sich stdoutum dasselbe erste Wort handelt (und gelangt zur idxVariable)
  • [ -n ${idx}" ] just checks ifidx` ist nicht leer

Antwort2

Ich weiß, es ist alt, aber ich habe es einfach in einer Schleife so gemacht:

for ln in $( history | grep my_phrase | cut -f2 -d' '); do
    history -d $ln
done
  • $(...)- Befehlssubstitution, Rückgabe stdoutvon...
  • cut -f2 -d' '- schneidet die 2. Spalte der durch Leerzeichen getrennten Ausgabe ab, also die Zeilennummer
  • history -d $ln- entfernt die angegebene Zeilennummer aus dem Verlauf

Einzeiler zum einfachen Kopieren und Einfügen:

for ln in $( history | grep my_phrase | cut -f2 -d' '); do history -d $ln; done

Antwort3

Sie könnten verwenden sed, um Einträge aus zu entfernen .bash_history.
Da es sich jedoch um ein Passwort handelt, würde ich Ihnen raten, Ihre .bashrcDatei zu bearbeiten und sicherzustellen, dass die Zeile mit auf oder HISTCONTROLgesetzt ist , um zu vermeiden, dass Sie das Passwort erneut in der CLI eingeben müssen . Auf diese Weise können Sie Befehle eingeben und sie nicht in den Verlauf einfügen, wenn sie mit einem Leerzeichen beginnen: ignorebothignorespacebash

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

Beachten Sie das Leerzeichen zwischen $und dem Befehl. Dadurch würde die Zeile im Bash-Verlauf ignoriert.

-i: bedeutet, die Datei inline zu bearbeiten.
dBedeutet letztendlich, die Zeile zu entfernen, die den Ausdruck dazwischen enthält /.

Diese Lösung funktioniert nur unter Linux GNU sed.

verwandte Informationen