Estou tentando trocar variáveis de ambiente e restaurá-las rapidamente entre terminais.
Eu defino duas funções no meu shell ( ~/.bashrc
):
save_env(){
mkdir -p ~/tmp
printenv > ~/tmp/env
}
load_env(){
source ~/tmp/env
}
Ambos funcionam conforme o esperado, exceto quando há ponto e vírgula ( ;
) em variáveis de ambiente, por exemplo
LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:
Quando usado load_env
, obtém erros como
34:ln=01: command not found
36:mh=00:pi=40: command not found
33:so=01: command not found
Como posso consertar isso?
;
não seria o único personagem problemático. Qualquer caractere especial na sintaxe do shell também seria. Isso inclui espaço,|&<>*?[]~#'"\$^()
pelo menos nova linha.printenv
(um comando não padrão) é impressoname=value
seguido por um caractere de nova linha para cada variável de ambiente no ambiente que ele próprio recebe. Ele imprime esses nomes e valores brutos. Não pretende produzir código shell. Na verdade, ele também imprimirá variáveis de ambiente cujo nome não pode ser mapeado para variáveis de shell.Obviamente, ele não imprimirá variáveis de shell que não sejam exportadas para o ambiente, incluindo variáveis array ou assoc e, claro, parâmetros de shell não variáveis, como
$1
,$2
,$!
,$$
...Especificamente no caso do
bash
shell, ele imprimirá as variáveis de ambiente especiaisbash
usadas para exportar funções exportadas. Exemplo:Para salvar as variáveis do shell que são exportadas para o ambiente, você pode usar
export -p
(padrão, mas a saída que ele produz para um determinado shell só pode ser usada no mesmo shell (e na versão dele, e no mesmo sistema operacional (libc) e localidade )).Por exemplo, com nosso exemplo acima:
Na verdade, essas três variáveis foram definidas internamente pelo próprio bash.
OLDPWD
é exportado, mas não definido neste caso.Observe como o bash é usado
declare -x
em vez deexport
na saída. Isso significa que quando o código resultante é interpretado dentro de uma função, as variáveis resultantes serão locais para a função. Para contornar isso, você pode definir aposix
opção:Veja no entanto como
OLDPWD
é exportado, mas não definido nem desdefinido, portanto, ao restaurar, seu valor permanecerá inalterado. O mesmo aconteceria com qualquer variável que você exportasse, mas não definisse.Então, você
save_env
poderia ficar assim:E
load_env
:(
command
para evitar sair do shell em caso de erro se o bash estiver no modo POSIX).local -
(não padrão e copiado do shell Almquist) para fazer alterações nas opções locais da função, é necessária uma versão relativamente recente do bash. Com versões mais antigas, você sempre pode usar um subshell em vez de um grupo de comandos como corpo dasave_env
função:Lembre-se também de que o bash armazena as configurações da opção em sua
SHELLOPTS
variável (a variante de opção longa do$-
parâmetro). Se essa variável for exportada (o que não é aconselhável), essaposix
opção acabará incluída no valor impresso porexport -p
.Para imprimir todas as variáveis (não apenas as exportadas) e seus valores, você pode usar
set
sozinho, mas cuidado, não inclui informações de atributos (como exportado, somente leitura, inteiro...) e no caso do bash também inclui funções. Como isso também inclui variáveis somente leitura, você também receberá erros ao obter o resultado.Como no shell Korn ou zsh,
typeset -p
pode ser usado para imprimir definições de variáveis, incluindo seu tipo e atributos, mas comoexport -p
quando não está noposix
modo, a saída terá coisas comodeclare -- var="value"
quando as fontes dentro de uma função criariam a variável local para a função.Desde a versão 4.4, o bash também possui um
${var@A}
que se expande para o código que poderia ser usado para redefinir aquela variável, e que você pode usar com${!varname@A}
o operador indireto, mas dá uma saída meio bastarda: darávar='value'
para uma variável escalar sem atributo , masdeclare -x var='value'
caso contrário (com o mesmo problema acima), e para matrizes vazias ou assocs fornecedeclare -a var
/declare -A var
(desde 5.1) em vez dedeclare -a var=()
/declare -A var=()
(e nada nas versões anteriores), portanto, é bastante inútil no geral.Com zsh em vez de bash, você teria mais controle sobre quais variáveis deseja selecionar e como elas são descartadas.
zsh
possui uma$parameters
matriz associativa especial que mapeia nomes de variáveis para seus tipos e atributos.Por exemplo,
print -raC2 -- ${(kv)parameters}
toprint
,k
eys ev
alues dessa associaçãor
aw em2
C
olumns (a
cross) gera algo como:Para imprimir apenas a definição de
scalar
variáveis que não estãospecial
nemreadonly
ocultas, você faria:Se executado dentro de uma função, ele adicionará uma
-g
opção¹ àstypeset
linhas de comando geradas (exceto para aquelas variáveis que são locais para a função) que evitam tornar a variável local se for originada novamente dentro de uma função.¹ O bash
typeset
também tem uma-g
opção, mas isso coloca variáveis no escopo mais externo, em vez de evitar tornar a variável local, se ainda não for, por isso é bastante inútil.