Eu estava escrevendo um script bash e atualizei o código (salvou o arquivo de script em disco) enquanto o script aguardava alguma entrada em um whileloop. Depois que voltei ao terminal e continuei com a invocação anterior do script, o bash deu um erro sobre a sintaxe do arquivo:
/home/aularon/bin/script: line 58: unexpected EOF while looking for matching `"'
/home/aularon/bin/script: line 67: syntax error: unexpected end of file
Então, tentei fazer o seguinte:
1º: crie um script, self-update.shvamos chamá-lo:
#!/bin/bash
fname=$(mktemp)
cat $0 | sed 's/BEFORE\./AFTER!./' > $fname
cp $fname $0
rm -f $fname
echo 'String: BEFORE.';
O que o script faz é ler seu código, alterar a palavra 'ANTES' para 'APÓS' e depois reescrever-se com o novo código.
2º Execute:
chmod +x self-update.sh
./self-update.sh
3ª maravilha ...
aularon@aularon-laptop:~$ ./self-update.sh
String: AFTER!.
Agora, eu não teria imaginado que, na mesma invocação, sairia DEPOIS! , na segunda execução, com certeza, mas não na primeira.
Então, minha pergunta é: é intencional (por design)? ou é por causa da maneira como o bash executa o script? Linha por linha ou comando por comando. Existe algum bom uso desse comportamento? Algum exemplo disso?
Edit: Eu tentei reformatar o arquivo para colocar todos os comandos em uma linha, ele não funciona agora:
#!/bin/bash
fname=$(mktemp);cat $0 | sed 's/BEFORE\./AFTER!./' > $fname;cp $fname $0;rm -f $fname;echo 'String: BEFORE.';
Resultado:
aularon@aularon-laptop:~$ ./self-update.sh #First invocation
String: BEFORE.
aularon@aularon-laptop:~$ ./self-update.sh #Second invocation
String: AFTER!.
Ao mover a echostring para a próxima linha, separe-a da cpchamada rewriting ( ):
#!/bin/bash
fname=$(mktemp);cat $0 | sed 's/BEFORE\./AFTER!./' > $fname;cp $fname $0;rm -f $fname;
echo 'String: BEFORE.';
E agora funciona novamente:
aularon@aularon-laptop:~$ ./self-update.sh
String: AFTER!.