Comprender el signo de exclamación (!) En bash

108

solía

history | less

para obtener las líneas de comandos anteriores y de los números en el lado izquierdo, encontré la línea que quería repetir (por ejemplo, 22) e hice

!22

en el símbolo del sistema y funcionó, ejecutando el conjunto de comandos en la línea que hice en ese momento. No puedo entender dónde se usa el signo de exclamación, qué representa en términos de acciones tomadas por bash y dónde usarlo. De la documentación no veo una explicación que sea 'tangible'.

Vass
fuente
66
Esta respuesta podría ayudar
Michael Mrozek
99
No es una respuesta a su pregunta, pero <ctrl> + R le permitirá buscar interactivamente su historial y luego ejecutarlo inmediatamente si encuentra lo que estaba buscando.
kasterma

Respuestas:

144

!es una característica que apareció originalmente en el shell C , en los días anteriores a la posibilidad de contar con terminales para tener teclas de flecha. Es especialmente útil si agrega el número de comando actual al prompt ( PS1="\!$ ") para que pueda mirar rápidamente su pantalla para obtener números de comandos anteriores.

Ahora que puede usar las teclas de flecha y cosas como Ctrl-Rbuscar en el historial de comandos, no veo mucho uso para la función.

Una variante de la que aún puede encontrar útil es la !!que vuelve a ejecutar el comando anterior. Por sí solo, no encuentro !!Enternada más rápido que solo Enter, pero puede ser útil cuando se combina en un comando más grande.

Ejemplo: Un error piloto común en los sudosistemas basados ​​es olvidar el sudoprefijo en un comando que requiere privilegios adicionales. Un novato vuelve a escribir todo el comando. El estudiante diligente edita el comando desde el historial de comandos del shell. El iluminado escribe sudo !!.

Bash le permite deshabilitar el !procesamiento en el shell con set +o histexpando set +H. Puede deshabilitarlo en Zsh con set -K.

Warren Young
fuente
44
Encuentro que Ctrl-P Ctrl-J es bastante rápido; más rápido que Up Enter, al menos.
Ephemient
24
Si solo desea ejecutar el último comando, Up / Enter está bien, pero si desea agregarlo de alguna manera (por ejemplo, olvidó sudoo algo), puede hacerlo sudo !!, por ejemplo. Eso podría ser un poco más rápido que "Arriba / Ctrl-A (o Inicio, si tienes la suerte) / sudo / space / enter". YMMV. :)
1
@AquariusPower: solo cítalo. Ya sea echo 'Hi!'o echo "Hi!"o echo Hi\!. Todos hacen lo mismo.
Warren Young
1
setopt NO_BANG_HISTen zsh podría ser más memorable que -K.
Gregory
48

Si no hay una respuesta más larga aquí, ciertamente hay una en Super Usuario, ya que he leído una recientemente. En la página de manual de bash puedes encontrar una gran sección titulada HISTORY EXPANSION sobre el tema.

Puede hacer un host completo más que simplemente ejecutar el último comando, o el número de comando X. Puede hacer cosas como !catejecutar el último comando que comenzó con cat. O !?bash?:s/bash/csh/ejecuta el último comando que contiene bashpero lo reemplaza con csh.

Llora Havok
fuente
3
Aunque no es directamente una respuesta a la pregunta de OP, esto necesita mucho más votos a favor. ¡Tan útil! Gracias Havok.
malvim
Debería mirar la página de manual antes de empezar a buscar en Google.
erikbwork
1
!!:s/bash/csh/en realidad ejecuta el último comando , luego reemplaza bash con csh, si está presente. No es el último comando que incluyó bash. Eso sería !?bash?:s/bash/csh/o tal vez!?bash?:s/%/csh/
cde
Después de haber usado Bash ampliamente durante varios años, me sorprendió descubrir que nunca antes había conocido esta palabra clave, y aunque he pasado horas estudiando detenidamente las manpáginas, esta característica es increíblemente oscura. Gracias por señalar la sección relevante: ese es el único lugar en los documentos reales donde lo explican lo suficiente.
Steve Benner
39

Se puede hacer mucho más con !:

  • ejecute un comando que se escribe antes de 3 comandos: !-3
  • ejecutar un comando que comienza con !ls

y mucho más. Vea 15 ejemplos de expansión del historial de Linux Bash que debe conocer

usuario379997
fuente
Votó esto. Ninguna de las otras respuestas tenía ninguno de estos ingeniosos trucos.
Gergely Lukacsy
Votado porque www.thegeekstuff.com es simplemente un recurso fantástico, y este fue uno de los pocos artículos de Linux que no había visto antes. Muy útil.
Steve Benner
4

Un amigo mío me envió un correo electrónico esto:

Es parte de la biblioteca de historia GNU. En bash se usa para volver a ejecutar comandos en su historial. Si quieres ser hardcore, grep para history_expansion_char en bash-4.1 / lib / readline / histexpand.c para detalles de implementación.

Vass
fuente
3

Por supuesto, puede hacer !!para reutilizar el último comando en bash shell. Y luego hay !$que reutilizar la última parte de su último comando.

por ejemplo, ver algún archivo

less path/to/your/file.txt

Si ahora desea editar el mismo archivo, puede usar !$para obtener solo la ruta del archivo desde el último comando

vim !$
Teshan Shanuka J
fuente
1
Ah, esperaba encontrar esto. ¿Cómo se comporta con dos args?
Jonathan
Simplemente reutilizará el último argumento de los dos. $touch f1 f2y luego $vim !$evaluará a$vim f2
Teshan Shanuka J