Onde "export var = value" não está disponível?

31

Eu percebi - provavelmente na Usenet em meados dos anos 90 (!) - que a construção

export var=value

é um bashismo, e que a expressão portátil é

var=value
export var

Eu venho defendendo isso há anos, mas recentemente alguém me desafiou e não consigo encontrar nenhuma documentação para apoiar o que costumava ser uma sólida crença minha.

Pesquisar no Google "export: command not found"parece não trazer nenhum caso em que alguém realmente tenha esse problema; portanto, mesmo que seja genuíno, acho que não é muito comum.

(Os hits que recebo parecem ser iniciantes que copiam / colam pontuação e acabam com 'export: command not foundalgo assim, ou tentando usá export-lo sudo; e cshusuários novatos tentando usar a sintaxe do shell Bourne.)

Certamente posso dizer que ele funciona no OS X e em várias distribuições Linux, incluindo as que shestão dash.

sh$ export var=value
sh$ echo "$var"
value
sh$ sh -c 'echo "$var"'  # see that it really is exported
value

No mundo de hoje, é seguro dizer que export var=valueé seguro usar?

Eu gostaria de entender quais são as consequências. Se não é portátil para a v7 "Bourne classic", isso não passa de trivial. Se houver sistemas de produção em que o shell realmente não possa lidar com essa sintaxe, seria útil saber.

triplo
fonte
2
obrigado finalmente entendi por que vejo tantas vezes aquilo que pensei que era inútil: var = value; export var
Agente de Thorsten
2
Ainda existem algumas caixas Solaris, e essas são notoriamente frugal em suas ferramentas padrão; do outro lado do espectro, não busyboxvem com sua própria concha mínima? (Eu não estou em uma posição para tentar qualquer direito esta segunda.)
Ulrich Schwarz
Graças a Ulrich, o Solaris pode muito bem ser o culpado por essa longa sintaxe ainda estar por aí.
Thorsten Staerk

Respostas:

20
export foo=bar

não era suportado pelo shell Bourne (um shell antigo dos anos 70 do qual derivam shimplementações modernas como ash / bash / ksh / yash / zsh). Isso foi introduzido por ksh.

No shell Bourne, você faria:

foo=bar export foo

ou:

foo=bar; export foo

ou com set -k:

export foo foo=bar

Agora, o comportamento de:

export foo=bar

varia de casca para casca.

O problema é que atribuições e argumentos simples de comando são analisados ​​e interpretados de maneira diferente.

O foo=baracima é interpretado por alguns shells como um argumento de comando e por outros como uma atribuição (algumas vezes).

Por exemplo,

a='b c'
export d=$a

é interpretado como:

'export' 'd=b' 'c'

com algumas conchas ( ash, versões mais antigas de zsh(na emulação sh) yash) e:

'export' 'd=b c'

nos outros ( bash, ksh).

Enquanto

export \d=$a

ou

var=d
export $var=$a

seria interpretado da mesma forma em todas as conchas (as 'export' 'd=b' 'c') porque essa barra invertida ou cifrão interrompe as conchas que a suportam a considerar esses argumentos como atribuições.

Se exportele próprio for citado ou resultar de alguma expansão (mesmo em parte), dependendo da concha, também deixaria de receber o tratamento especial.

Consulte " São necessárias cotações para atribuição de variável local? " Para obter mais detalhes sobre isso.

A sintaxe Bourne:

d=$a; export d

é interpretado da mesma forma por todos os shells sem ambiguidade ( d=$a export dtambém funcionaria no shell Bourne e nos shells compatíveis com POSIX, mas não nas versões recentes, zshexceto em shemulação).

Pode ficar muito pior que isso. Veja, por exemplo, uma discussão recente sobrebash quando matrizes estão envolvidas.

(OMI, foi um erro introduzir esse recurso ).

Stéphane Chazelas
fonte
Fiquei surpreso que o ponto-e-vírgula não é necessário foo=bar export foo, como eu sempre o vi lá. Sei que a exportação é integrada, mas por que foo=bar; foo=baz export foo; echo $foose comporta de maneira diferente foo=bar; foo=baz /bin/cat /dev/null; echo $foo?
Jrw32982 suporta Monica
3
@ jrw32982, porque é um builtin. Você começa ainda que em conchas POSIX modernos, mas apenas para especiais builtins que exporté.
Stéphane Chazelas
Embora discuta declare, não export, recomendo que quem se preocupa com segurança leia a discussão no link que o StéphaneChazelas forneceu ao bash.bugs .
John1024
Ótima resposta! Mas levou muito tempo para chegar d=$a export dé interpretado da mesma por todos os conchas sem ambigüidade ;-)
conny
@ Conny, d=$a export dnão funciona mais zsh, então eu atualizei a resposta. Veja editar.
Stéphane Chazelas
28

Não é um basismo, mas uma sintaxe compatível com POSIX. Na verdade, ele começou como um kshismo há muito tempo e foi posteriormente adotado por quase todos os shells Bourne baseados em sintaxe. A única exceção notória é /bin/shno Solaris 10 e mais antigo, que segue a sintaxe herdada do shell Bourne. Felizmente, o Solaris 11 usa um shell compatível com POSIX como /bin/sh.

A propósito, exportjá era um comando embutido no shell herdado de Bourne, pelo que pesquisar no Google export: command not foundera enganador.

Aqui está o comportamento do shell Bourne herdado quando exportcombinado com uma afetação:

$ export var=22
var=22: is not an identifier

Para os nostálgicos, o código fonte deste shell Bourne original está disponível e pode ser compilado para a maioria das distribuições Unix e Linux.

jlliagre
fonte
Muito obrigado pelo insight histórico e pela mensagem de erro correta ao Google! Obvious em retrospecto, rubor ...
tripleee
4
Esse não é o código-fonte do shell Bourne original, é um OpenSolaris sh modificado. É a concha Bourne, mas depois de décadas de evolução. A casca originais Bourne, como fornecido com Unix V7 podem ser encontrados no Heritage Society Unix
Stéphane Chazelas
1
@ StéphaneChazelas A rigor, você está correto como sempre. Observe, no entanto, que eu não escrevi "o shell Bourne original", mas "este shell Bourne original", como estava me referindo ao shell usado pelo Solaris 10 e seu código-fonte que pode ser compilado em plataformas modernas. Observe também que o shell Bourne teve vários recursos adicionados entre 1977 e 1989, mas depois deixou de evoluir (fora da portabilidade / adaptação a plataformas mais recentes e correções de bugs) nos últimos 25 anos.
Jlliagre 28/03