
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
}
tac
invertiert die Zeilen der Ausgabe (einige Beiträge wiesen darauf hin, dass dies nicht bei allen Systemen der Fall ist)[-z $1 ]
:true
wenn das erste an die Funktion () übergebene Argument$1
leer ist.mapfile -t
(manpage;einige Führer): lieststdin
in 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$n
Variablen.'{pring $1}'
liest fürführeprint
eine 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 idx
Nummer des erhalten haben history
und 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 sichstdout
um dasselbe erste Wort handelt (und gelangt zuridx
Variable)[ -n ${idx}" ] just checks if
idx` 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ückgabestdout
von...
cut -f2 -d' '
- schneidet die 2. Spalte der durch Leerzeichen getrennten Ausgabe ab, also die Zeilennummerhistory -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 .bashrc
Datei zu bearbeiten und sicherzustellen, dass die Zeile mit auf oder HISTCONTROL
gesetzt 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: ignoreboth
ignorespace
bash
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.
d
Bedeutet letztendlich, die Zeile zu entfernen, die den Ausdruck dazwischen enthält /
.
Diese Lösung funktioniert nur unter Linux GNU sed
.