È utile avere l'ultimo commento errato per correggerlo, ma subito dopo diventa spazzatura potenzialmente confusa.
Il mio approccio è in due passaggi: memorizza i comandi che falliscono quando lo fanno e li rimuove più tardi.
Memorizza i comandi che falliscono quando lo fanno:
error_handler() {
FAILED_COMMANDS="$(history | tail -1l | cut -c -5) $FAILED_COMMANDS"
}
trap error_handler ERR
trap command signals
viene eseguito command
quando uno di signals
è "sollevato".
$(command)
, esegue command
e acquisisce il suo output.
Quando il comando non riesce, questo frammento di codice acquisisce il numero di cronologia dell'ultimo comando salvato nella cronologia e lo memorizza in una variabile per la futura cancellazione.
Semplice, ma funziona in modo errato con HISTCONTROL
e HISTIGNORE
- quando il comando non viene salvato nella cronologia a causa di una delle variabili, il numero di cronologia dell'ultimo comando salvato nella cronologia è quello del comando precedente; quindi, se un comando errato non viene salvato nella cronologia, il comando precedente verrà eliminato.
Versione leggermente più complicata, che funziona correttamente in quel caso:
debug_handler() {
LAST_COMMAND=$BASH_COMMAND;
}
error_handler() {
local LAST_HISTORY_ENTRY=$(history | tail -1l)
# if last command is in history (HISTCONTROL, HISTIGNORE)...
if [ "$LAST_COMMAND" == "$(cut -d ' ' -f 2- <<< $LAST_HISTORY_ENTRY)" ]
then
# ...prepend it's history number into FAILED_COMMANDS,
# marking the command for deletion.
FAILED_COMMANDS="$(cut -d ' ' -f 1 <<< $LAST_HISTORY_ENTRY) $FAILED_COMMANDS"
fi
}
trap error_handler ERR
trap debug_handler DEBUG
Rimuovi i comandi memorizzati qualche tempo dopo:
exit_handler() {
for i in $(echo $FAILED_COMMANDS | tr ' ' '\n' | uniq)
do
history -d $i
done
FAILED_COMMANDS=
}
trap exit_handler EXIT
Spiegazione:
All'uscita da Bash, per ogni numero di cronologia univoco rimuovere la corrispondente voce di cronologia,
quindi deselezionare FAILED_COMMANDS
per non rimuovere i comandi che hanno ereditato i numeri di cronologia da comandi già eliminati.
Se sei sicuro che FAILED_COMMANDS
sarà privo di duplicati, puoi semplicemente iterare su di esso
(es. Scrivere for i in $FAILED_COMMANDS
). Se, tuttavia, ti aspetti che non sia ordinato dal più grande al più piccolo (in questo caso lo è sempre), sostituiscilo uniq
con sort -rnu
.
I numeri di cronologia FAILED_COMMANDS
devono essere univoci e ordinati dal più grande al più piccolo, perché quando si elimina la voce, i numeri dei comandi successivi vengono spostati, ad es. quando si emette history -d 2
, la terza voce diventa seconda, la quarta diventa terza, ecc.
A causa di ciò, quando si utilizza questo codice, non è possibile chiamare manualmente history -d <n>
dove n
è minore o uguale al maggior numero memorizzato inFAILED_COMMANDS
e si aspettano il codice per funzionare correttamente.
E 'probabilmente una buona idea di agganciare exit_handler
a EXIT
, ma si può anche chiamare in qualsiasi momento prima.