¿Cómo eliminar todas las entradas que contienen una cadena particular del comando de historial en BASH?

¿Cómo eliminar todas las entradas que contienen una cadena particular del comando de historial en BASH?

¿Existe algún comando o forma de eliminar todas las entradas del historial de bash Shell que contienen una cadena en particular? Esto será útil para eliminar comandos del historial que contengan contraseña. Sé que podemos eliminar cada entrada del historial por su número, pero el problema es que solo elimina una entrada a la vez y necesito sacar el número cada vez para eliminar una nueva entrada.

p.ej. El comando de historial muestra 5 entradas que contienen la contraseña abcabc y quiero eliminar todas las entradas del comando de historial que contienen la cadena abcabc

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

Intenté seguir el comando que dio el error que se indica a continuación

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

Expectativa: No hay errores y se deben eliminar todas las entradas que contengan la cadena abcabc.

Respuesta1

Otro similar a la respuesta de @cprn pero usando awk(en lugar de cut) y una función:

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
}
  • tacinvierte las líneas de salida (algunas publicaciones señalaron que no es común a todos los sistemas)
  • [-z $1 ]: truesi el primer argumento pasado a la función ( $1) está vacío.
  • mapfile -t(página de manual;algunas guías): lee stdinen una variable de matriz ( result)
    • "${result[@]}"devuelve la matriz
  • awk '{print $1}'(guía de usuarios de GNU,guías breves,página de manual): se utiliza para ambos: identificar una coincidencia y procesarla. Divide los datos delimitados por espacios en blanco (predeterminado) y los almacena en las $nvariables.
  • '{pring $1}'lee pararealizar printacción en la primera palabra.

Uso:

del_word_history history
del_word_history abcabc
history -w

Lo siguiente es unsolución más limpiaque comprueba si obtuvimos el idxnúmero de history, en lugar de alguna otra palabra de una entrada de varias líneas:

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
}

Las principales diferencias son:

  • obtenemos las líneas completas en la variable de matriz linesa través demapfile
  • awk '{ if ($1 ~ /^[0-9]+$/) { print $1 }}'comprueba que la primera palabra de cada línea es un número, y es stdoutesa misma primera palabra (y llega a la idxvariable)
  • [ -n ${idx}" ] just checks ifidx` no está vacío

Respuesta2

Sé que es antiguo pero lo hice en un bucle así:

for ln in $( history | grep my_phrase | cut -f2 -d' '); do
    history -d $ln
done
  • $(...)- sustitución de comandos, devoluciones stdoutde...
  • cut -f2 -d' '- corta la segunda columna de la salida delimitada por espacios, es decir, el número de línea
  • history -d $ln- elimina el número de línea dado del historial

Una línea para copiar y pegar fácilmente:

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

Respuesta3

podrías utilizar sedpara eliminar entradas de .bash_history.
Pero como es una contraseña para evitar escribirla nuevamente en la CLI, le recomendaría que edite su .bashrcarchivo y se asegure de que la línea with HISTCONTROLesté configurada en ignorebotho ignorespace. Esto le permitiría escribir un comando bashy no ponerlos en el historial si comienzan con un espacio:

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

Observe el espacio entre $el comando y esto haría que la línea se ignore en el historial de bash.

-i: significa editar el archivo en línea.
dal final significa eliminar la línea que contiene la expresión entre /.

Esta solución sólo funciona en Linux GNU sed.

información relacionada