En bash, ¿cómo puedo escapar de un signo de exclamación?


183

Quiero hacer algo así bzr commit -m "It works!". Puedo escapar del signo de exclamación haciendo algo bzr commit -m "It works\!". Sin embargo, mi mensaje de confirmación incluye la barra diagonal inversa. ¿Cómo escapo el signo de exclamación, mientras sigo ignorando la barra invertida?


1
Haciendo bzr commit -m "It works"!trabajos también.
kba

1
Como señalé antes, el comando que pones realmente funciona por sí solo :)bzr commit -m "It works!"
h4unt3r


1
Aunque la respuesta aceptada es una buena solución para sus problemas de confirmación, creo que no es una respuesta al problema real: la expansión del historial de Bash . ¿Por favor considera aceptar la respuesta de Dennis?
Arjan

Respuestas:


153

Como no depende de bash para expandir las variables en su mensaje de confirmación, puede usar comillas simples en su lugar. Las cadenas entre comillas simples no se expanden con bash.

bzr commit -m 'This does work!' 

24
Dado que la pregunta era "¿Cómo puedo escapar de un signo de exclamación?" y no "¿Cómo no amplío un signo de exclamación?" No creo que esto sea válido. Algunas veces (como al pasar apóstrofes y signos de exclamación en la misma línea de comando) esto no funciona. La respuesta a continuación funciona mucho mejor para hacer lo que mucha gente necesita.
Jann

77
@ Janan: Tienes 100% de razón en esto, pero creo que el problema aquí es el que tiene tantas preguntas sobre el superusuario: ¿Respondemos la pregunta al punto o ayudamos a las personas a resolver su problema específico? Creo que ambas formas pueden ser útiles, y esto buscaba ayuda sobre un tema específico.
Benjamin Bannier

touché! Este era un problema específico. Solo tiendo a querer una respuesta a mis preguntas para poder usarla en muchas situaciones. pS: La razón por la que incluso mencioné esto fue porque necesitaba pasar un apóstrofe y un signo de exclamación a un programa perl y necesitaba la solución a continuación. :)
Jann

Estoy de acuerdo con Benjamin y Jann pero di un voto negativo. El título de la pregunta está indexado por los motores de búsqueda y así es como llegué aquí y probablemente la mayoría de los usuarios vengan aquí. Por eso creo que es importante que la pregunta real refleje el problema detrás de esto. En otros foros, se aconseja a las personas (casi obligadas) que pregunten con precisión qué buscan. Responder preguntas mal expresadas respalda la descuido y esa es la razón exacta de mi voto negativo aquí. Como compromiso / solución, mi sugerencia es ayudar a adaptar el encabezado para que refleje el problema real.
ChristophK

153

Aquí hay otro método si desea comillas dobles y la exclamación:

echo "It's broken"'!'

Esto funciona incluso si !no está al final de la línea.

Por ejemplo:

echo "hello there"'!'" and goodbye"

Bonificación: se puede usar una técnica similar para escapar de cualquier texto en Sh o Bash (con la ayuda de sed): vea la primera opción en esta respuesta . Además, si ha bash-completioninstalado, es probable que ya tenga la quote()función disponible.


44
Buen consejo, JWD. No me di cuenta de que las cadenas de bash podrían concatenarse simplemente omitiendo espacios en blanco entre ellas.
Alan H.

En realidad, si el signo de exclamación está al final de la cadena que está en el claro echo "Happy birthday!", funcionará como se esperaba, de lo contrario, puede escapar con una barra invertida, pero la barra invertida también se imprimirá XD Bash no es para los débiles :)
h4unt3r

@ h4unt3r: Extraño, esa no es mi experiencia. Para mí, echo "Happy Birthday!"salidas 2 líneas. El primero es echo "Happy birthday"(sin exclamación), y el segundo es "Feliz cumpleaños" (nuevamente, sin exclamación). ¿Tiene activada la expansión del historial cuando realiza esta prueba?
jwd

@jwd ¿qué versión de bash estás ejecutando? Siempre tengo hist expansión en. ¿Usaste accidentalmente dos! para tu prueba?
h4unt3r

@ h4unt3r: version 4.1.2(1)-release (x86_64-redhat-linux-gnu)definitivamente solo se !está utilizando uno . Tengo histexpandpresente en $SHELLOPTS. Sin embargo, acabo de probar la versión 4.3.18 (2) en otra máquina, y se comporta como lo describiste. Supongo que fue un error que se solucionó.
jwd

66

Desactiva la expansión del historial :

set +H

o

set +o histexpand

Puede agregar uno de esos comandos a su ~/.bashrcsi generalmente no usa la expansión del historial.

Bash 4.3 agregó un caso especial :

el carácter de expansión del historial también se trata como citado si precede inmediatamente a la comilla doble de cierre en una cadena entre comillas dobles


Gracias, esto funcionó, pero tuve que hacerlo set +o histexpand, no set -o histexpand. ¿Podrías editar tu respuesta para arreglar esto?
Mateo

Vaya, error tipográfico, lo siento. Fijo.
Dennis Williamson

excelente! estaba buscando esto para EDADES ... gracias vm! como escape no funcionará ... No quiero usar comillas simples también ... ¡¡¡Agregaré esto a mi .bashrcthx !!, nunca usado !en scripts y para nada !! siempre fue preocupante ...
Aquarius Power

¡Esto es genial! echo "@AquariusPower!"
joehanna

12

Use comillas simples (') en lugar de comillas dobles ("). Las comillas simples desactivan toda interpretación de las cosas en ellas, mientras que las comillas dobles solo desactivan algunas.

bzr commit -m 'It works!'

4

Acabo de encontrar otra forma, que al menos funcionará con echocadenas (oraciones) que desea puntuar con un signo de exclamación. Hace una ejecución final, más o menos, alrededor de Bash histexpand y toma solo un poco más de tiempo para codificar.

El hexadecimal para un signo de exclamación, como se enumera en http://www.ascii-code.com/ , es 21, por lo que si coloca \x21al final de su cadena echo -e $foo, haga $foosu propio eco expandido [es decir, foo=$(echo -e "$foo")] lo que obtener cuando de echo $foonuevo es la cadena con un !al final. Y tampoco cambiar de histexpand.

Funciona seguro en Bash 4+. Versiones anteriores, ymmv.


Hmmm no me funciona.
lzap

No entiendo lo que estás diciendo acerca de hacerse eco. 'echo -e' e 'printf' interpretan los códigos octal, hexadecimal y Unicode escapados. En los casos en que use cualquiera de esos, puede usar "\ 041" (el octal para el "!") O "\ x21" (el hexadecimal) para sustituir el signo de exclamación. Por ejemplo: printf "OMG\041". Si está creando una cadena entre comillas dobles en algún lugar que no sea echo o printf, como la cadena de confirmación sobre la que se le preguntó a OP, puede incrustar $(echo -e "\041")en la cadena donde debería estar el signo de exclamación. De esta manera: bzr commit -m "This is a great commit$(echo -e "\041")".
Todd Walton
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.