it-swarm-es.tech

¡Cómo hacer eco de una explosión!

Traté de crear un script al echo 'incluir el contenido en un archivo, en lugar de abrirlo con un editor

echo -e "#!/bin/bash \n /usr/bin/command args"  > .scripts/command

La salida :

bash:!/bin/bash: evento no encontrado

He aislado este extraño comportamiento al explosión .

$ echo !
!  

$ echo "!"
bash: !: event not found

$ echo \#!
#!

$ echo \#!/bin/bash
bash: !/bin/bash: event not found
  • ¿Por qué está causando esto la explosión?
  • ¿Cuáles son estos "eventos" a los que se refiere bash?
  • ¿Cómo puedo superar este problema e imprimir "#!/Bin/bash" en la pantalla o en mi archivo?
59
Stefan

Intenta usar comillas simples.

echo -e '#!/bin/bash \n /usr/bin/command args'  > .scripts/command

echo '#!'

echo '#!/bin/bash'

El problema se produce porque bash está buscando en su historial!/Bin/bash. El uso de comillas simples escapa a este comportamiento.

62
Richm

Como Richm dijo , bash está tratando de hacer un coincidencia de historial . Otra forma de evitarlo es escapar de la explosión con un \:

$ echo \#\!/bin/bash
#!/bin/bash

Sin embargo, tenga en cuenta que entre comillas dobles, el \ no se elimina:

$ echo "\!"
\!
18
Michael Mrozek

! comienza una sustitución del historial (un "evento" es una línea en el historial del comando); por ejemplo !ls se expande a la última línea de comando que contiene ls, y !?foo se expande a la última línea de comando que contiene foo. También puede extraer palabras específicas (por ejemplo, !!:1 se refiere a la primera palabra del comando anterior) y más; Vea el manual para más detalles.

Esta característica se inventó para recuperar rápidamente los comandos anteriores en los días en que la edición de la línea de comandos era primitiva. Con los shells modernos (al menos bash y zsh) y copiar y pegar, la expansión del historial ya no es tan útil como solía serlo, sigue siendo útil, pero puede sobrevivir sin ella.

Puede cambiar qué carácter desencadena la sustitución del historial configurando la variable histchars; si rara vez usa la sustitución del historial, puede establecer, p. histchars='¡^' así que eso ¡ activa la expansión del historial en lugar de !. Incluso puedes desactivar la función por completo con set +o histexpand.

Para poder deshabilitar la expansión del historial en una línea de comando particular, puede usar space como el tercer carácter de $histchars:

histchars='!^ '

Luego, si ingresa su comando con un espacio inicial, no se realizará la expansión del historial.

bash-4.3$ echo "#!/bin/bash"
bash: !/bin/bash: event not found
bash-4.3$  echo "#!/bin/bash"
#!/bin/bash

Sin embargo, tenga en cuenta que los espacios iniciales también se usan cuando $HISTCONTROL contiene ignorespace como una forma de decirle a bash que no registre una línea de comando en el historial.

Si desea ambas funciones de forma independiente, deberá elegir otro personaje como el tercer personaje de $histchars. Desea uno que no afecte la forma en que se interpreta su comando. Algunas opciones:

  • usando la barra invertida (\): \echo foo funciona pero tiene el efecto secundario de deshabilitar alias o palabras clave.
  • PESTAÑA: para insertarlo en la primera posición, debe presionar Ctrl+VTab aunque.
  • si no te importa escribir dos teclas, puedes elegir cualquier personaje que normalmente no aparezca en la primera posición (%, @, ?, elige el tuyo) y crea un alias vacío para él:

    histchars='!^%'
    alias %=
    

    Luego ingrese ese carácter, espacio y su comando:

    bash-4.3$ % echo !!
    !!
    

(no podrá grabar un comando donde la sustitución del historial ha sido desactivada. Tenga en cuenta también que el tercer carácter predeterminado de $histchars es # para que la expansión del historial no se realice en los comentarios. Si lo cambia e ingresa comentarios en el mensaje, ¡debe tener en cuenta el hecho de que! las secuencias pueden expandirse allí).

4
Stéphane Chazelas

Las soluciones propuestas no funcionan, por ejemplo, en el siguiente ejemplo:

$ bash -c "echo 'hello World!'"
-bash: !'": event not found
$

En este caso, la explosión se puede imprimir utilizando su código octal ASCII:

$ bash -c "echo -e 'hello World\0041'"
hello World!
$
2
Atti

Una solución simple que aún no se menciona es usar una variable:

$ var='!'
$ echo -e "#${var}/bin/bash \n /usr/bin/command args"  > .scripts/command

Imprimir un bang! es no un problema cuando la cadena no está entre comillas o está entre comillas simples o dentro de una C-String

$ echo hi\!pal 'hi!pal' $'hi!pal'
hi!pal 'hi!pal' $'hi!pal'

Tampoco es un problema cuando histexpand está deshabilitado (_ shopt -ou histexpand o set +o histexpand o simplemente set +H. También es posible cambiar los caracteres hisexpand para que sea más fácil imprimir un bang!.

Pero la solución portátil más simple es: usar un var

$ var='!'
$ echo "hi${var}pal"
hi!pal
0
Isaac