¿La expansión del historial está deshabilitada en los scripts?

9

Entiendo que el siguiente error se debe al !uso para la expansión del historial:

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

Sin embargo, si pongo el comando en un script y ejecuto el script, no hay problema:

$ cat myscript
echo "Hello!Tim"
$ bash myscript 
Hello!Tim

¿Porqué es eso? ¿El manual de bash menciona la razón?

Tim
fuente
1
Buena pregunta, simplemente dicho. ¡Muy bien hecho!
Comodín el
Según lo que estoy leyendo aquí: gnu.org/software/bash/manual/html_node/History-Interaction.html Creo que necesitaría usar algún tipo de shoptmodificador para que funcione en su script. Sé que esa no es realmente la respuesta que estás buscando.
jesse_b
¿Cuál es el caso de uso? ¿Qué tipo de script ejecutarías que expandiría tu historial anterior? ¿O expandiría los comandos anteriores del script?
Jeff Schaller
@JeffSchaller, la expansión del historial numérico en un script con números positivos parece una muy mala idea, pero fácilmente podría imaginar casos de uso para !!o !-2(números de historial negativos / relativos) o similares. En su mayoría, se resolverían mejor de otras maneras, pero sigue siendo una buena pregunta sobre cómo funciona el shell (¡y cuándo necesita / no necesita escapar de sus exclamas!).
Comodín el

Respuestas:

12

Sí, la expansión del historial está habilitada de manera predeterminada solo para shells interactivos.

Para habilitarlo para un script de shell, escriba:

set -H

Para deshabilitarlo en un shell interactivo, escriba:

set +H

Para determinar si la expansión del historial está actualmente habilitada o no, use alguna forma del siguiente código:

case $- in (*H*) echo enabled ;; (*) echo disabled ;; esac

Al comenzar a enseñar una clase de shell, busqué exhaustivamente el manual para tratar de establecer qué es realmente un "shell interactivo". Es una pregunta de hidromasaje, así que déjame ahorrarte algunos problemas:

La carcasa tiene MUCHAS opciones. Algunas de estas opciones se inicializan de diferentes maneras cuando el shell tiene un terminal de control (o cuando se inicia con -i, bla, bla, lo que sea, ver más abajo).

TODAS las opciones del shell se pueden cambiar individualmente.

Un "shell interactivo" es un término engañoso cuando intenta definirlo con precisión. Realmente es solo una colección de configuraciones de opciones.

La pregunta sobre qué configuraciones hacen que un shell sea interactivo o no es imposible de responder; Se pone ridículo. Es precisamente la misma pregunta filosófica que la Nave de Teseo .

Si inicia un shell interactivo, pero luego deshabilita la expansión del historial, usa el --noeditingindicador, establece --norc, apaga expand_aliases, etc., etc., ¿en qué sentido es el shell interactivo? O, ¿cuándo deja de ser interactivo? No puedes responder estas preguntas.

La verdad es que "interactivo" es solo una etiqueta conveniente para una colección de varias opciones de shell. Del mismo modo "no interactivo". La misma cosa; solo una colección de comportamientos que pueden cambiarse individualmente.

En pocas palabras: el shell se comporta de manera diferente cuando se inicia "interactivamente" frente a cuando se inicia "no interactivamente". Intentar definir con precisión estos términos después de la puesta en marcha es una tontería. Basta con mirar cada opción individual del shell para comprender su comportamiento.


Había olvidado que, además de mi propia investigación, publiqué mucho sobre esto en este mismo sitio.

Comodín
fuente
Gracias. En el manual, solo encuentro "Esta opción está activada de forma predeterminada para shells interactivos" para set -H. Probablemente deduzca que "la expansión del historial está habilitada de manera predeterminada solo para shells interactivos".
Tim
@Tim, mira el resto de mi respuesta. Esa oración del manual es muy resbaladiza y trata de obtener la respuesta a "¿Qué ES un caparazón interactivo?" fuera de la página del manual es como hablar en círculos. No va a ninguna parte.
Comodín el
Lo que PUEDE decir es que el siguiente fragmento de código siempre le mostrará si la expansión del historial está habilitada en el shell actual:case $- in (*H*) echo enabled ;; (*) echo disabled ;; esac
Comodín
@Tim, por cierto, no tengo idea de lo que quieres decir con que es mi "inferencia", porque ese es el significado claro de set -H. Esa es la opción histexpand.
Comodín el
1
He intentado esto en un script y no funcionó hasta que también lo hice set -o history, después de verificar con set -oel script que estaba deshabilitado.
Daniel C. Sobral