Pregunta ¿Qué es "-bash:!": Evento no encontrado "


Intenta ejecutar lo siguiente bajo un shell bash echo "Reboot your instance!"

En mi instalación:

root@domU-12-31-39-04-11-83:/usr/local/bin# bash --version
GNU bash, version 4.1.5(1)-release (i686-pc-linux-gnu)
Copyright (C) 2009 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
root@domU-12-31-39-04-11-83:/usr/local/bin# uname -a
Linux domU-12-31-39-04-11-83 2.6.35-22-virtual #35-Ubuntu SMP Sat Oct 16 23:57:40 UTC 2010 i686 GNU/Linux
root@domU-12-31-39-04-11-83:/usr/local/bin# echo "Reboot your instance!"
-bash: !": event not found

¿Alguien puede explicar qué es "eventos de bash?" Nunca he escuchado este concepto antes. Además, ¿cómo debo salir "!" al final de la frase?


88
2017-12-02 10:45


origen




Respuestas:


Puedes desactivar la sustitución de historial usando set +H.


40
2017-12-02 16:31



¿Conoces el razonamiento detrás de la sintaxis? Parece realmente contrario a la intuición. Pensarías que escribirías +H para habilitar algo y -H para deshabilitar algo. - PunkyGuy
@PunkyGuy: no sé la historia (juego de palabras intencional) detrás de él, pero las opciones de Unix generalmente comienzan con un guión (o menos) y + es simplemente lo opuesto a eso. - Dennis Williamson


! es un carácter especial para bash, se usa para referirse a comandos anteriores; p.ej,

!rm

recuperará y ejecutará el último comando que comenzó con la cadena "rm", y

!rm:p

recuperará pero no ejecutará el último comando que comenzó con la cadena "rm". Bash está interpretando el signo de exclamación en echo "reboot your instance!" como "Sustituya aquí el último comando que comenzó con los caracteres inmediatamente después del signo de exclamación.", y se queja a usted de que no puede encontrar un evento (comando) en su historial que comenzó con una sola comilla doble.

Tratar

echo reboot your instance\!

para proteger (escapar) el signo de exclamación de bash.


86
2017-12-02 10:49



Sí, pero debería suceder si quiero usar echo -e "algo de texto $ ENV_VAL algo más de texto \ n ¡Reinicia ahora!" ? - Maxim Veksler
Escribe dos declaraciones de eco; obtienes la línea de alimentación de forma gratuita. - MadHatter
La solución simple es usar comillas simples y comillas dobles a la vez: echo -e "Text \ nReeboot" '!' - mmey
Esto apesta Si no me escapo del signo de exclamación, bash lanza un ataque. Si yo hacer Escápalo, la barra invertida está incluida en la cadena final. ¿Por qué haces esto, Bash? (pastebin.com/g4PYv56A) - Hubro
@Hubro, para ser justos, no estoy seguro de que todo sea culpa de Bash. Tienes asuntos un tanto complicados al usar ruby ​​para alimentar cosas para golpear, y no me queda claro qué papel desempeña ruby ​​en la eliminación o el refuerzo de los personajes de escape. - MadHatter


Para resolver su problema original, intente usar comillas simples, en lugar de comillas dobles. Con este último, bash intentará expandir ciertos caracteres antes de pasar el resultado al comando (eco en este caso). Con comillas simples, bash pasa toda la cadena, sin cambios.

! se utiliza en los comandos para referirse al historial de la línea de comandos. Ver: http://tldp.org/LDP/abs/html/abs-guide.html#HISTCOMMANDS para un conjunto completo. Con el ejemplo anterior, bash está tratando de expandirse !" como una referencia a un evento antes de que echo obtenga un vistazo, de ahí el error.

Tenga en cuenta que en los scripts, todos Los comandos de historial están deshabilitados, ya que solo tienen sentido en una shell interactiva.

El único que uso regularmente, es !$. Se expande hasta el último argumento del comando anterior. Es una taquigrafía útil en algunos lugares.


22
2017-12-02 11:02



!! Para completar el último comando ingresado es muy útil; particularmente, sudo !! o pfexec !! - jgoldschrafe
También encuentro que sudo y pfexec son buenas utilidades, pero no hay necesidad de ser tan entusiasta. - LeartS
$_ trabaja en más shells que bash y es una variable adecuada, a diferencia de !$. (y @LeartS: Me gustó la falta de emoticones de tu broma.;)) - ΤΖΩΤΖΙΟΥ


Solo pon un espacio entre! y "que funcionará.

Aclamaciones.


5
2017-09-25 07:06



¿Podría por favor agregar una explicación de por qué su solución funciona? - 200_success
Esto funciona porque Bash solo trata! como un carácter especial si es seguido directamente por un carácter que no es un espacio en blanco. Sin embargo, también agregará un espacio en blanco adicional a su salida, por lo que no siempre se puede desear ... - mmey


Si es un carácter especial para bash, se usa para referirse a comandos anteriores.

Algunas de las formas en que puede manejar la situación

Lo siguiente dará salida a la cadena como está

echo 'Reboot your instance!'

Lo siguiente ejecutará el comando y concatenará la cadena.

echo 'escaping #'" adding `which python` to the string"
echo '#!'`which python`

2
2018-04-25 13:57





En bash 4.3 Parece que ya no necesitas usar comillas simples o set +H:

$ bash --version
GNU bash, version 4.3.46(1)-release (x86_64-unknown-linux-gnu)
[...]
$ echo "Reboot your instance!"
Reboot your instance!

1
2017-07-12 14:43



Probablemente un error, porque aquí tengo 4.4.12 y una vez más, necesito set +H o citando. O tienes set +H en algún lugar (como en /etc/profile). - Bodo Thiesen
El uso de! -Char no al final de la oración verifica que la detección de eventos de bash todavía funciona bien. La versión es 4.3.30 ........ $ echo "Vuelva a revisar su oración! Foo" bash:! Foo: evento no encontrado - JohnnyD92


También podrías usar un heredoc:

cat <<EOF
Reboot your instance!
EOF

Es molesto en este caso porque no es de una sola línea, pero para comandos más largos (como escribir un script de bash), funciona muy bien.


0
2017-07-07 11:41