it-swarm.com.de

Wie kann ich Duplikate in meiner .bash_history entfernen, um die Reihenfolge beizubehalten?

Ich genieße es wirklich, control+r Zu verwenden, um meinen Befehlsverlauf rekursiv zu durchsuchen. Ich habe ein paar gute Optionen gefunden, die ich gerne damit verwende:

# ignore duplicate commands, ignore commands starting with a space
export HISTCONTROL=erasedups:ignorespace

# keep the last 5000 entries
export HISTSIZE=5000

# append to the history instead of overwriting (good for multiple connections)
shopt -s histappend

Das einzige Problem für mich ist, dass erasedups nur sequentielle Duplikate löscht - so dass mit dieser Befehlsfolge:

ls
cd ~
ls

Der Befehl ls wird tatsächlich zweimal aufgezeichnet. Ich habe darüber nachgedacht, regelmäßig mit cron zu laufen:

cat .bash_history | sort | uniq > temp.txt
mv temp.txt .bash_history

Dies würde das Entfernen der Duplikate erreichen, aber leider würde die Reihenfolge nicht beibehalten. Wenn ich die Datei nicht zuerst sort, glaube ich nicht, dass uniq richtig funktionieren kann.

Wie kann ich Duplikate in meiner .bash_history entfernen, um die Reihenfolge beizubehalten?

Extra Gutschrift:

Gibt es Probleme beim Überschreiben der Datei .bash_history Über ein Skript? Wenn Sie beispielsweise eine Apache-Protokolldatei entfernen, müssen Sie ein Nohup/Reset-Signal mit kill senden, damit die Verbindung zur Datei gelöscht wird. Wenn dies bei der Datei .bash_history Der Fall ist, könnte ich vielleicht irgendwie ps verwenden, um zu überprüfen, ob keine verbundenen Sitzungen vorhanden sind, bevor das Filterskript ausgeführt wird?

69
cwd

Verlauf sortieren

Dieser Befehl funktioniert wie sort|uniq, Hält jedoch die Zeilen an Ort und Stelle

nl|sort -k 2|uniq -f 1|sort -n|cut -f 2

Grundsätzlich wird jeder Zeile ihre Nummer vorangestellt. Nach sort|uniq - werden alle Zeilen gemäß ihrer ursprünglichen Reihenfolge (unter Verwendung des Zeilennummernfelds) zurücksortiert und das Zeilennummernfeld aus den Zeilen entfernt.

Diese Lösung hat den Fehler, dass es nicht definiert ist, welcher Vertreter einer Klasse gleicher Linien es in der Ausgabe schafft, und daher ist seine Position in der endgültigen Ausgabe undefiniert. Wenn jedoch der letzte Vertreter ausgewählt werden soll, können Sie die Eingabe mit einem zweiten Schlüssel sort:

nl|sort -k2 -k 1,1nr|uniq -f1|sort -n|cut -f2

Verwalten von .bash_history

Zum erneuten Lesen und Zurückschreiben des Verlaufs können Sie history -a Und history -w Verwenden.

37
artistoex

Also suchte ich genau das Gleiche, nachdem ich mich über Duplikate geärgert hatte, und stellte fest, dass, wenn ich mein ~/.bash_profile (Mac) bearbeite mit:

export HISTCONTROL=ignoreboth:erasedups

Es macht genau das, was Sie wollten, es hält nur die neuesten Befehle. ignoreboth ist eigentlich genau wie ignorespace:ignoredups und das zusammen mit erasedups erledigt den Job.

Zumindest auf meinem Mac-Terminal mit Bash funktioniert das perfekt. Fand es hier auf askubuntu.com .

57
sprite

Diese Lösung in freier Wildbahn gefunden und getestet:

awk '!x[$0]++'

Wenn zum ersten Mal ein bestimmter Wert einer Zeile ($ 0) angezeigt wird, ist der Wert von x [$ 0] Null.
Der Wert Null wird mit ! Invertiert und wird Eins.
Eine Anweisung, die zu eins ausgewertet wird, verursacht die Standardaktion print.

Daher wird ein bestimmtes $0 Gedruckt, wenn es zum ersten Mal angezeigt wird.

Bei jedem nächsten Mal (den Wiederholungen) wurde der Wert von x[$0] Inkrementiert.
Der negierte Wert ist Null, und eine Anweisung, die mit Null ausgewertet wird, wird nicht gedruckt.

Um den letzten wiederholten Wert beizubehalten, kehren Sie den Verlauf um und verwenden Sie dieselbe awk:

awk '!x[$0]++' ~/.bash_history                 # keep the first value repeated.

tac ~/.bash_history | awk '!x[$0]++' | tac     # keep the last.
21
Clayton Stanley

Antwort von Clayton erweitern:

tac $HISTFILE | awk '!x[$0]++' | tac | sponge $HISTFILE

tac kehren Sie die Datei um, stellen Sie sicher, dass Sie moreutils installiert haben, damit sponge verfügbar ist, andernfalls verwenden Sie eine temporäre Datei.

12
Ali Shakiba

Dies ist ein alter Beitrag, aber ein ständiges Problem für Benutzer, die mehrere Terminals geöffnet haben möchten und deren Verlauf zwischen Fenstern synchronisiert, aber nicht dupliziert werden soll.

Meine Lösung in .bashrc:

shopt -s histappend
export HISTCONTROL=ignoreboth:erasedups
export Prompt_COMMAND="history -n; history -w; history -c; history -r"
tac "$HISTFILE" | awk '!x[$0]++' > /tmp/tmpfile  &&
                tac /tmp/tmpfile > "$HISTFILE"
rm /tmp/tmpfile
  • die Option histappend fügt den Verlauf des Puffers am Ende der Verlaufsdatei hinzu ($ HISTFILE).
  • ignorieren und Löschen verhindern, dass doppelte Einträge in der $ HISTFILE gespeichert werden
  • Der Befehl Eingabeaufforderung aktualisiert den Verlaufs-Cache
    • history -n liest alle Zeilen aus $ HISTFILE, die möglicherweise seit dem letzten Wagenrücklauf in einem anderen Terminal aufgetreten sind
    • history -w schreibt den aktualisierten Puffer in $ HISTFILE
    • history -c löscht den Puffer, sodass keine Duplizierung auftritt
    • history -r liest die $ HISTFILE erneut und hängt sie an den jetzt leeren Puffer an
  • das awk-Skript speichert das erste Vorkommen jeder Zeile, auf die es stößt. tac kehrt es um und kehrt es dann zurück, damit es mit den neuesten Befehlen gespeichert werden kann, die noch im Verlauf des Verlaufs sind
  • rm die/tmp Datei

Jedes Mal, wenn Sie eine neue Shell öffnen, werden in der Historie alle Dupes gelöscht und jedes Mal, wenn Sie die drücken Enter Wenn Sie ein anderes Shell-/Terminalfenster eingeben, wird dieser Verlauf aus der Datei aktualisiert.

7
smilingfrog

Diese würden die letzten duplizierten Zeilen behalten:

Ruby -i -e 'puts readlines.reverse.uniq.reverse' ~/.bash_history
tac ~/.bash_history | awk '!a[$0]++' | tac > t; mv t ~/.bash_history
6
Lri

Es ist schwierig, jeden neuen Befehl eindeutig aufzuzeichnen. Zuerst müssen Sie zu ~/.profile Oder ähnlichem hinzufügen:

HISTCONTROL=erasedups
Prompt_COMMAND='history -w'

Dann müssen Sie zu ~/.bash_logout Hinzufügen:

history -a
history -w
0
Steven Penny