A expansão do histórico está desativada nos scripts?

9

Entendo que o erro a seguir deve ser !usado para expansão do histórico:

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

No entanto, se eu colocar o comando em um script e executá-lo, não há problema:

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

Por que é que? O manual do bash menciona o motivo?

Tim
fonte
1
Boa pergunta, simplesmente. Muito bem feito!
Curinga
Com base no que estou lendo aqui: gnu.org/software/bash/manual/html_node/History-Interaction.html Eu acredito que você precisaria usar algum tipo de shoptmodificador para que ele funcione em seu script. Eu sei que essa não é realmente a resposta que você está procurando.
jesse_b
Qual é o caso de uso? Que tipo de script você executaria que expandiria seu histórico anterior? Ou expandiria os comandos anteriores do script?
Jeff Schaller
@JeffSchaller, a expansão numérica do histórico em um script com números positivos parece uma péssima ideia, mas eu poderia facilmente imaginar casos de uso para !!ou !-2(números históricos negativos / relativos) ou similares. Principalmente, eles seriam resolvidos melhor de outras maneiras, mas ainda é uma boa pergunta sobre como o shell funciona (e quando você faz / não precisa escapar dos exclams!).
Wildcard

Respostas:

12

Sim, a expansão do histórico é ativada por padrão apenas para shells interativos.

Para habilitá-lo para um script de shell, escreva:

set -H

Para desativá-lo em um shell interativo, escreva:

set +H

Para determinar se a expansão do histórico está ou não ativada no momento, use alguma forma do seguinte código:

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

Ao começar a dar uma aula de shell, procurei o manual extensivamente para tentar estabelecer o que realmente é um "shell interativo". É uma questão de redemoinho, então deixe-me lhe poupar alguns problemas:

O shell tem muitas opções. Algumas dessas opções são inicializadas de maneiras diferentes quando o shell possui um terminal de controle (ou quando iniciado com -iblá blá, o que seja, veja abaixo).

TODAS as opções do shell podem ser alteradas individualmente.

Um "shell interativo" é um termo enganoso quando você tenta defini-lo com precisão. É realmente apenas uma coleção de configurações de opções.

A pergunta sobre quais configurações tornam um shell interativo ou não é impossível responder; fica ridículo. É precisamente a mesma pergunta filosófica que a nave de Teseu .

Se você iniciar um shell interativo, mas desativar a expansão do histórico, use o --noeditingsinalizador, defina --norc, desative expand_aliasesetc., etc., em que sentido o shell é interativo? Ou quando não se torna mais interativo? Você não pode responder a estas perguntas.

A verdade é que "interativo" é apenas um rótulo conveniente para uma coleção de várias opções de shell. Da mesma forma "não interativo". Mesma coisa; apenas uma coleção de comportamentos que podem ser alterados individualmente.

Conclusão: o shell se comporta de maneira diferente quando é iniciado "interativamente" em comparação com quando é iniciado "não interativamente". Tentar definir com precisão esses termos após a inicialização é uma tolice. Basta olhar para cada opção individual do shell para entender seu comportamento.


Eu tinha esquecido que, além de minha própria pesquisa, publiquei extensivamente sobre isso neste mesmo site.

Curinga
fonte
Obrigado. No manual, só encontro "Esta opção está ativada por padrão para shells interativos" para set -H. Provavelmente, você deduz que "a expansão do histórico é ativada por padrão apenas para shells interativos".
Tim
@ Tim, veja o resto da minha resposta. Essa frase do manual é muito escorregadia e tenta obter a resposta para "o que é um shell interativo?" sair da página de manual é como falar em círculos. Não vai a lugar nenhum.
Wildcard
O que você PODE dizer é que o seguinte trecho de código sempre mostrará se a expansão do histórico está ativada no shell atual:case $- in (*H*) echo enabled ;; (*) echo disabled ;; esac
Curinga
@ Tim, a propósito, não tenho idéia do que você quer dizer com "minha inferência", porque esse é o significado claro de set -H. Essa é a opção histexpand.
Curinga
1
Eu tentei isso em um script e não funcionou até que eu também fiz set -o history, depois de verificar com set -oo script que ele estava desativado.
Daniel C. Sobral