Em Guia de script Bash avançado , em exemplo 27-4 , sétima linha a partir do fim, li isto:
Uma função é executada como um subprocesso.
Fiz um teste no Bash e parece que a afirmação acima está errada.
Pesquisas em este site, Bash Man e meu mecanismo de pesquisa não trazem nenhuma luz.
Você tem a resposta e gostaria de explicar?
Comentários
- Como observado, esse guia é enganador ao extremo. Em vez disso, recomendo o Guia Wooledge Bash .
- Um fato importante é que ” Bash ” evita criar subshells. Eles são caros, possuem ambiente próprio e afetam o desempenho do script e também a forma como o código flui (muitas vezes, de forma inconveniente, para lidar com suas particularidades). O estado real do Bash é produto de uma evolução, uma evolução do código. Quer dizer, a primeira versão do Bash usa mais subshells *** do que a real. Esse tipo de inconsistência parece razoável. *** se você quiser uma prova, não posso ‘ dar a você. Eu ‘ deduzi-o de páginas da web, comentários … Eu ‘ li essa declaração em algum lugar atrás.
Resposta
O Guia de script Bash avançado nem sempre é confiável e seus scripts de exemplo contêm práticas desatualizadas, como o uso do efetivamente descontinuado crases para substituição de comando, ou seja, `command`
em vez de $(command)
.
Neste caso específico, é flagrantemente incorreto.
A seção sobre Funções do shell no Bash (canônico) o manual afirma definitivamente que
As funções do shell são executadas no contexto do shell atual; nenhum novo processo é criado para interpretá-los.
Comentários
- ” Guia de script Bash avançado geralmente não é confiável ” Muito verdadeiro.
- Você pode fornecer referências para apoiar o seu primeira frase?
- @WillVousden como seria uma referência aqui? Um monte de exemplos das deficiências técnicas do guia ‘ s? Um documento onde os especialistas da comunidade bash notaram anteriormente que ele não é confiável? Ajudaria se um membro stackoverflow com um distintivo dourado em bash concordasse em um comentário? : p
- @WillVousden Eu não ‘ não acho que o que você quer existe em uma forma confiável. Mendel Cooper atualizou e corrigiu problemas com o guia no passado, mas não há rastreador de bug público ou lista de erratas. (Talvez essa seja a declaração mais contundente que posso fazer.) Então, quando encontramos uma falha (percebida ou real), tudo o que podemos fazer é enviar um e-mail para o autor e esperar o melhor.
- @WillVousden, .. .se você quiser um histórico de há quanto tempo o consenso no canal freenode #bash é de que o ABS deve ser evitado, consulte lãedge.org/ ~ greybot / meta / abs – o segundo campo em cada linha é o carimbo de data / hora e o primeiro é o nome de usuário; Eu ‘ espero que seja suficiente a afirmação de que os nomes de usuário em questão são pessoas muito respeitadas.
Resposta
As funções do Curly Brace serão executadas no processo do shell de chamada, a menos que precisem de seu próprio subshell, que é:
- quando você os executa em segundo plano com
&
- quando você os executa como um link em um pipeline
Redirecionamentos ou env. as variáveis não irão forçar um novo subshell:
hw(){ echo hello world from $BASHPID echo var=$var } var=42 hw >&2 echo $BASHPID #unexports var=42 and restores stdout here
Se você definir a função com parênteses em vez de curvas:
hw()( echo hello world from $BASHPID ) hw echo $BASHPID
ele sempre será executado em um novo processo.
A substituição do comando $()
também sempre cria processos em bash (mas não em ksh se você executa builtins dentro dele).
Comentários
- Eu não ‘ não sabia
f() (...)
é permitido. Existem outras definições além de{...}
e(...)
? No Bash, eu ‘ m não em outros ainda. - @tomas Você pode usar a sintaxe
function hw { echo hello world; }
(sem necessidade de()
se você digitarfunction
e pode especificar redirecionamentos logo após o final}
ou)
como emhw(){ echo error; } >&2
. Isso ‘ é sobre isso. - Isso é a resposta na qual pensei imediatamente, e é absolutamente correta.Deve ser votada como a resposta correta.
f()(...)
sempre executa um shell próprio, enquantof(){...}
não. - NB funções bash aceitam qualquer comando composto, portanto
foo() [[ x = x ]]
também é uma definição de função válida. No entanto, se você olhar para a função comtype foo
, ‘ verá que ainda é um açúcar sintático parafoo() { [[ x = x ]]; }
. O mesmo é verdadeiro para funções de subshell:bar() ( : )
torna-sebar() { ( : ); }
. - @kojiro nice +1. não ‘ não sabia disso
Resposta
O comando em a pergunta desse exemplo se parece com:
echo ${arrayZ[@]/%e/$(replacement)}
O exemplo posterior afirma:
# $( ... ) is command substitution. # A function runs as a sub-process.
Sendo caridoso com o ABS Guide, o que eles aparentemente queriam escrever é que a função é executada dentro de uma substituição de comando e o comando dentro de uma substituição de comando é executado em um subshell .
Comentários
- Isso ‘ é muito enganador. Obrigado pela sua interpretação.
- @tomas ” muito enganador. ” Sim, muito. Em contraste com o Guia ABS, Greg ‘ s Wiki é uma excelente fonte de informações avançadas de bash.
- Saúde. Qual ‘ s sua opinião sobre este: wiki.bash-hackers.org/start ?
- @tomas Não tenho nenhum conhecimento de primeira mão sobre isso.
- @tomas, … minha própria opinião sobre o wiki do bash-hackers é que ‘ é uma excelente fonte. Eu ‘ não li isso de forma tão abrangente quanto fiz a wiki do Wooledge, mas tende a ser preciso e escrito com precisão.