Eu sei que Bash e Zsh suportam local
variáveis, mas existem sistemas que só têm shells compatíveis com POSIX. E local
é indefinido em shells POSIX.
Então eu quero perguntar quais shells suportam local
a palavra-chave para definir variáveis locais?
Edit/bin/sh
: Sobre shells quero dizer o shell padrão .
Não é tão simples quanto apoiar
local
ou não. Há muita variação na sintaxe e como isso é feito entre shells que têm uma forma ou outra de escopo local.É por isso que é muito difícil chegar a um padrão que concorde com todos. Veja http://austingroupbugs.net/bug_view_page.php?bug_id=767 para o esforço POSIX nessa frente.
o escopo local foi adicionado primeiro no ksh no início dos anos 80.
A sintaxe para declarar uma variável local em uma função era com
typeset
:(o suporte de função foi adicionado ao Bourne shell posteriormente, mas com uma sintaxe diferente (
f() command
) eksh
adicionado suporte para esse também posteriormente; o Bourne shell nunca teve escopo local (exceto, é claro, por meio de subshells))O
local
AFAIK integrado foi adicionado primeiro ao shell Almquist (usado em BSDs, dash, busybox sh) em 1989, mas funciona de maneira significativamente diferenteksh
dotypeset
.ash
derivados não suportamtypeset
como um alias paralocal
, mas você sempre pode definir um manualmente.bash e zsh adicionados
typeset
com aliaslocal
em 1989 e 1991, respectivamente.ksh88 adicionado
local
como um alias não documentado portypeset
volta de 1990 e pdksh e seus derivados em 1994.posh
(baseado empdksh
) removidotypeset
(para estrita conformidade com a Política Debian que requerlocal
, mas nãotypeset
).O POSIX inicialmente se opôs a especificar
typeset
com base no fato de que era um escopo dinâmico . Então ksh93 (uma reescrita de ksh em 1993 por David Korn) mudou para escopo estático . Também no ksh93, ao contrário do ksh88, o escopo local é feito apenas para funções declaradas com aksh
sintaxe (function f {...}
), não com a sintaxe Bourne (f() {...}
) e olocal
alias foi removido.No entanto, o ksh93v- beta e a versão final da AT&T podem ser compilados com um modo "bash" experimental (na verdade ativado por padrão) que faz escopo dinâmico (em formas de incômodo de funções, incluindo com
local
etypeset
) quandoksh93
é invocado comobash
.local
diferetypeset
nesse caso, pois só pode ser invocado de dentro de uma função. Essebash
modo será desabilitado por padrão no ksh2020, embora oslocal
/declare
aliasestypeset
sejam retidos mesmo quando o modo bash não estiver compilado (embora ainda com escopo estático).yash
(escrito muito mais tarde), temtypeset
(à la ksh88), mas só tevelocal
como alias desde a versão 2.48 (dezembro de 2018).@Schily (que infelizmente faleceu em 2021 ) costumava manter um descendente de shell Bourne que foi recentemente feito principalmente compatível com POSIX, chamado
bosh
que suporta escopo local desde a versão 2016-07-06 (comlocal
, semelhante aash
).Portanto, os shells do tipo Bourne que têm alguma forma de escopo local para variáveis hoje são:
No que diz respeito aos
sh
diferentes sistemas, observe que existem sistemas em que o POSIXsh
está/bin
(a maioria) e outros em que não está (como o Solaris, onde está/usr/xpg4/bin
). Para ash
implementação em vários sistemas temos:Agora, onde eles diferem:
typeset
(ksh, pdksh, bash, zsh, yash) vslocal
(ksh88, pdksh, bash, zsh, ash, yash 2.48+).function f {...}
função), vs escopo dinâmico (todos os outros shells). Por exemplo, sejamfunction f { typeset v=1; g; echo "$v"; }; function g { v=2; }; f
saídas1
ou2
. Veja também como oexport
atributo afeta o escopo noksh93
.local
/typeset
apenas torna a variável local (ash
,bosh
), ou cria uma nova instância da variável (outros shells). Por exemplo, sev=1; f() { local v; echo "${v:-empty}"; }; f
saídas1
ouempty
(veja também alocalvar_inherit
opção no bash 5.0 e acima).export
) e/ou tipo e quais da variável no escopo pai. Por exemplo, se imprimeexport V=1; f() { local V=2; printenv V; }; f
ou nada.1
2
zsh
) ou não está definida inicialmente.unset V
em uma variável em um escopo local deixa a variávelunset
, ou apenas descasca um nível de escopo (mksh
,yash
,bash
em algumas circunstâncias). Por exemplo, se asv=1; f() { local v=2; unset v; echo "$v"; }
saídas1
ou nada (veja também alocalvar_unset
opção no bash 5.0 e acima)export
, se é uma palavra-chave ou apenas um mero built-in ou ambos e sob que condição é considerado como uma palavra-chave.export
, se os argumentos são analisados como argumentos de comando normais ou como atribuições (e sob quais condições).v=value myfunction
ondemyfunction
se declarav
como local ou não.Esses são os que estou pensando agora. Verifique o bug do grupo austin acima para mais detalhes.
No que diz respeito ao escopo local para opções de shell (em oposição a variables ), os shells que o suportam são:
ksh88
(com ambas as sintaxes de definição de função): feito por padrão, não conheço nenhuma maneira de desativá-lo.ash
(desde 1989): comlocal -
. Torna o$-
parâmetro (que armazena a lista de opções) local.ksh93
: agora feito apenas parafunction f {...}
funções.zsh
(desde 1995). Comsetopt localoptions
. Tambémemulate -L
para que o modo de emulação (e seu conjunto de opções) seja local para a função.bash
(desde 2016) comlocal -
like emash
, mas apenas para as opções geridas porset
, não as geridas porshopt
.¹ o POSIX
sh
no Solaris é/usr/xpg4/bin/sh
(embora tenha muitos bugs de conformidade, incluindo as opções locais para funções)./bin/sh
até o Solaris 10 era o shell Bourne (portanto, sem escopo local), e como o Solaris 11 é ksh93Para acompanhar uma dica na resposta de Stéphane, usando subshells você obtém o efeito local . Eu não tenho acesso a um shell POSIX verdadeiro, mas isso funciona no busybox
ash
- declare suas funções com()
parênteses em vez de{}
chaves. Isso força a função a ser executada em um subshell.saídas
Isso mostra que a função tem acesso a variáveis globais, e definir variáveis na função não altera as globais. Esta é uma técnica que às vezes uso quando quero alterar
$IFS
oucd
para um diretório diferente, mas não quero que essas ações afetem o resto do programa.