Es bueno tener el último comentario incorrecto para corregirlo, pero poco después se convierte en basura potencialmente confusa.
Mi enfoque es de dos pasos: almacenar comandos que fallan cuando lo hacen y eliminarlos en algún momento posterior.
Almacenar comandos que fallan cuando lo hacen:
error_handler() {
FAILED_COMMANDS="$(history | tail -1l | cut -c -5) $FAILED_COMMANDS"
}
trap error_handler ERR
trap command signals
se ejecuta command
cuando uno de ellos signals
está "elevado".
$(command)
, ejecuta command
y captura su salida.
Cuando el comando falla, este fragmento de código captura el número de historial del último comando guardado en el historial y lo almacena en una variable para su eliminación futura.
Simple, pero funciona incorrectamente con HISTCONTROL
y HISTIGNORE
: cuando el comando no se guarda en el historial debido a una de las variables, el número de historial del último comando guardado en el historial es el comando anterior; entonces, si un comando incorrecto no se guarda en el historial, el comando anterior se eliminará.
Versión un poco más complicada, que funciona correctamente en ese 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
Elimine los comandos almacenados más tarde:
exit_handler() {
for i in $(echo $FAILED_COMMANDS | tr ' ' '\n' | uniq)
do
history -d $i
done
FAILED_COMMANDS=
}
trap exit_handler EXIT
Explicación:
Al salir de Bash, para cada número de historial único, elimine la entrada de historial correspondiente,
luego borre FAILED_COMMANDS
para no eliminar comandos que heredaron números de historial de comandos ya eliminados.
Si está seguro de que FAILED_COMMANDS
estará libre de duplicados, puede iterar sobre él
(es decir, escribir for i in $FAILED_COMMANDS
). Sin embargo, si espera que no se ordene de mayor a menor (en este caso, siempre lo es), reemplácelo uniq
con sort -rnu
.
Los números de historial FAILED_COMMANDS
deben ser únicos y ordenados de mayor a menor, porque cuando elimina la entrada, los números de los siguientes comandos se desplazan, es decir. cuando emite history -d 2
, la tercera entrada se convierte en la segunda, la cuarta se convierte en la tercera, etc.
Debido a que, al utilizar este código, no se puede llamar de forma manual history -d <n>
, donde n
es menor o igual al mayor número almacenado enFAILED_COMMANDS
y esperar que el código funcione correctamente.
Es probablemente una buena idea conectar exit_handler
a EXIT
, pero también se puede llamar en cualquier momento anterior.