¿Cómo deshacer los cambios en el historial de comandos?

12

En los sistemas UNIX, puede presionar las flechas superior e inferior para navegar por los comandos anteriores. Esto es extremadamente útil.

A veces, subo y encuentro un comando que quiero usar de nuevo, pero con algunas variaciones. Si hago tales cambios, entonces no tengo una forma de recuperar el comando original, a menos que lo registre history.

¿Hay alguna forma de "deshacer" los cambios en el comando en el historial al que se accede a través de las teclas?

Mi solución actual es anteponer un #al comando. De esta manera, el comando actual se realiza como un comentario, por lo que no sucede nada. Luego, puedo navegar nuevamente a través de los comandos con las teclas. El problema es que el comando que estaba usando puede estar muy lejos en la lista, así que subir doscientas veces es un poco. Control + R tampoco es una solución, ya que es posible que no recuerde exactamente lo que estaba buscando.

Ejemplo

Escribí los siguientes "hace 50 comandos":

ls -l /etc/httpd/conf/

Ahora subí a esa línea y la cambié a

ls -l /etc/init.d/

pero no presionó enter. Ahora, quiero llegar al ls -l /etc/httpd/conf/nuevo.

Mi entorno

$ echo $SHELL
/bin/bash
$ echo $TERM
xterm
fedorqui
fuente
El hecho de que el historial de comandos haya cambiado es probablemente una característica (errónea) del shell que está utilizando. En ksh, por ejemplo, puede editar entradas del historial e invocarlas sin eliminar la "versión anterior" de la entrada; Tiene todos los comandos invocados disponibles.
Janis
Con "cambia" quiero decir que: dado un comando anterior que cambié después de alcanzarlo con las flechas, si voy arriba y abajo con las flechas, el comando anterior no mostrará la forma en que estaba, sino la forma en que modifiqué eso. Por supuesto, si escribo "enter" realizando un comando, ese comando anterior será como era inicialmente; pero esto es precisamente lo que estoy tratando de evitar y estoy buscando una manera de "restablecer" el comando a su valor inicial.
fedorqui
1
También en este caso, kshel comportamiento difiere aquí, parece. Y sus opciones de edición del historial también dependen del modo de edición elegido. En kshel modo vi, por ejemplo, la entrada anterior no se sobrescribe, y también puedo emitir un comando de deshacer, como en vi, con 'u'.
Janis
Uhms, esto suena muy prometedor. Ahora estoy trabajando en Bash y actualmente no estoy considerando cambiarme ksh, pero es bueno saber que tal cosa existe allí.
fedorqui
Me gustaría saber dónde bash almacena el historial de comandos reciente antes de escribir en el archivo de historial cuando se cierra el shell. Puede ayudar a determinar si esto es posible. ¿Cualquiera? Pensé que podría estar en una de las variables de shell, pero no tengo tiempo para estudiar el manual en este momento.
iyrin

Respuestas:

10

Mientras haya editado una entrada del historial pero Enteraún no la haya presionado , para volver a la entrada original, presione repetidamente Ctrl+ _- el undocomando - hasta que no se realicen más cambios. Has vuelto a la entrada original.

Gilles 'SO- deja de ser malvado'
fuente
5

Vuelva al comando original cuando haya realizado múltiples cambios en la línea:

revert-line (M-r) 
    Undo all changes made to this line. This is like 
executing the undo command enough times to get back to the beginning.

Mes la meta clave, que es altrpara mí.


Información gratuita pero útil

Cuando ha ejecutado un comando como OP lo había hecho anteriormente (sucede), no hay nada que "deshacer" porque los comandos son manejados y recordados por la biblioteca GNU Readline y no se escriben$HISTFILE hasta que se cierra el shell. La razón por la que menciono esto es porque se puede no sólo grepel $HISTFILEcomo uno podría esperar y puede que no sea ideal para salir del cascarón.

Así que aquí hay un par de opciones para evitar que te desplaces por todos los comandos anteriores de readline.

Si recuerda algunos de los comandos , presione ctrl+ ry escriba lo que recuerda para buscar en los comandos anteriores que contienen esa cadena. Al presionar ctrl+ rnuevamente se mostrará el siguiente más reciente, buscando hacia atrás.

Por ejemplo, escriba ls -la continuación ctrl+ rtantas veces como sea necesario para encontrar el comando anterior que buscan. Si te desplazas, ctrl+ sbuscará hacia adelante desde la posición actual.

El fccomando bash builtin es útil para enumerar los números de índice junto con los comandos anteriores de readline.

fc -l -100 enumerará los 100 comandos anteriores en readline.

Además, si OP sabe que está buscando un ls -lcomando anterior , podría canalizar la salida a grep:fc -l -100 | grep 'ls -l'

Esto debería generar una lista de ls -lcomandos anteriores precedidos por un número de índice. El resultado se ve así:
2065 ls -l

Ahora puede usar el designador de eventos !ndonde nestá el número de índice. En este ejemplo, la ejecución !2065se expandirá a ls -l.


Aunque no ayuda después del hecho, cualquiera que busque preservar el historial de comandos reciente al modificar comandos anteriores debería ver la HISTORY EXPANSIONsección de man bash. Aquí hay algunos métodos alternativos para modificar comandos antiguos sin sobrescribir el historial.

La Event Designatorssección muestra cómo puede editar fácilmente la cadena desde el comando utilizado más recientemente.

^string1^string2^
              Quick  substitution.  Repeat the previous command, replacing string1 with string2.  Equivalent to
              ``!!:s/string1/string2/'' (see Modifiers below).

Ejemplo:

$ echo foo
foo 
$ ^foo^bar
echo bar
bar

Los comandos más recientes ahora mostrarán:

echo foo
echo bar

El ejemplo anterior también explica cómo usar sedpara reemplazar una cadena en un designador de eventos.

!-n    Refer to the current command minus n.

Entonces, si hay 3 comandos en el historial, echo fooentonces usarías:
!-3:s/foo/bar

Tenga en cuenta que los designadores de eventos aparecerán en su historial como el comando ejecutado, en este caso echo bar. No aparecerá en la historia como !-3:s/foo/bar.

Simplemente lanzando eso por ahí, ya que parece estar estrechamente relacionado, incluso si es más un "no hacer" que la solución "deshacer" que OP está buscando.

iyrin
fuente
Esto es bueno, muchas gracias por la información detallada. Acepto la respuesta de Gilles, ya que hace exactamente lo que estoy buscando, mientras que aquí supones que sé muchas cosas sobre el comando que quiero rehacer, lo que no siempre es así.
fedorqui
Si estoy de acuerdo. Sería genial si esa función de deshacer se extendiera a los comandos que ingresé de alguna manera.
Iyrin