Portanto, isso é executado indefinidamente em Bash / dash / ksh / zsh (ou pelo menos até o seu disco ficar cheio):
#!/bin/sh
s=$0
foo() { echo "hello"; echo "foo" >> $s; sleep .1; }
foo
A única coisa a notar é que apenas o material acrescentado foi adicionado ao arquivo de script após a última linha que o shell leu. As conchas não voltam a reler as partes anteriores, o que elas nem poderiam fazer, se a entrada fosse um cano.
A construção similar não funciona em Perl, ele lê todo o arquivo antes de ser executado.
#!/usr/bin/perl -l
open $fd, ">>", $0;
sub foo { print "hello"; print $fd 'foo;' }
foo;
Podemos ver que isso também acontece quando é dada entrada através de um pipe. Isto dá um erro de sintaxe (e somente isso) após 1 segundo:
$ (echo 'printf "hello\n";' ; sleep 1 ; echo 'if' ) | perl
Embora o mesmo script seja canalizado para, por ex. Bash, imprime hello
e, em seguida, lança o erro de sintaxe um segundo depois.
O Python é parecido com o Perl com entrada canalizada, mesmo que o interpretador execute um loop de leitura e impressão quando estiver interativo.
Além de ler o script de entrada linha por linha, defina pelo menos argumentos de processo Bash e traço como eval
uma linha por vez:
$ cat evaltest.sh
var='echo hello
fi'
eval "$var"
$ bash evaltest.sh
hello
evaltest.sh: eval: line 4: syntax error near unexpected token 'fi'
evaltest.sh: eval: line 4: 'fi'
Zsh e ksh informam o erro imediatamente.
Similarmente para scripts originados, desta vez o Zsh também roda linha por linha, assim como o Bash e o dash:
$ cat sourceme.sh
echo hello
fi
$ zsh -c '. ./sourceme.sh'
hello
./sourceme.sh:2: parse error near 'fi'