Variáveis ​​locais no zsh: qual é o equivalente a "export -n" do bash no zsh

10

Estou tentando conter o escopo de uma variável em um shell e não ter filhos vendo isso no zsh. Por exemplo, eu digito isso em .zshrc:

GREP_OPTIONS=--color=always

Mas se eu executar um script de shell com o seguinte:

#!/bin/bash
echo $GREP_OPTIONS

A saída é:

--color=always

enquanto eu quero que seja nulo (o script do shell acima não deve ver a variável GREP_OPTIONS).

No bash, pode-se dizer:, o export -n GREP_OPTIONS=--color=alwaysque impedirá que isso aconteça. Como faço isso no zsh?

PonyEars
fonte
1
export -napenas exporta uma variável exportada.
terdon

Respostas:

11

exportem zsh é uma abreviação para typeset -gx, onde o atributo gsignifica "global" (ao contrário de local para uma função) e o atributo xsignifica "exportado" (ou seja, no ambiente). Portanto:

typeset +x GREP_OPTIONS

Isso também funciona no ksh e no bash.

Se você nunca exportar GREP_OPTIONSem primeiro lugar, não precisará exportar .

Você também pode usar a maneira indireta e portátil: desmarcar uma variável não a exporta. No ksh / bash / zsh, isso não funciona se a variável for somente leitura.

tmp=$GREP_OPTIONS
unset GREP_OPTIONS
GREP_OPTIONS=$tmp
Gilles 'SO- parar de ser mau'
fonte
Veja também env -u GREP_OPTIONS your-scriptcom algumas envimplementações (qualquer shell). Ou(unset GREP_OPTIONS; exec your-script)
Stéphane Chazelas
Eu tentei escrever + x, mas isso também não faz diferença. Como mostrado na minha pergunta, algo está exportando todas as variáveis ​​que eu defino, mesmo que eu não inclua "export". Ainda tentando descobrir o porquê.
PonyEars
@redstreet Talvez você tenha definido acidentalmente a opção export_all( -a)? Mas mesmo assim typeset +x GREP_OPTIONSnão exportaria a variável. Se você não encontrar o que está errado, tente a pesquisa binária: faça backup da sua .zshrc, remova a segunda metade, veja se o problema ainda existe, acrescente o terceiro trimestre ou reduza para o primeiro trimestre e repita.
Gilles 'SO- stop be evil'
@Gilles Obrigado, eu achei: zsh tem uma opção "allexport" que eu tinha no meu .zshrc. 'setopt noallexport' pode desativá-lo temporariamente, se ajudar mais alguém. Aceitarei sua resposta, pois ela foi a mais próxima.
PonyEars
Agora eu tenho um problema diferente, que está mais próximo do problema que estou tentando resolver, aqui: unix.stackexchange.com/questions/113645/…
PonyEars
6

Você pode usar uma função anônima para fornecer um escopo para a variável. De man zshall:

ANONYMOUS FUNCTIONS
       If no name is given for a function, it is `anonymous'  and  is  handled
       specially.  Either form of function definition may be used: a `()' with
       no preceding name, or a `function' with an immediately  following  open
       brace.  The function is executed immediately at the point of definition
       and is not stored  for  future  use.   The  function  name  is  set  to
       `(anon)'.

       Arguments to the function may be specified as words following the clos‐
       ing brace defining the function, hence if there are none  no  arguments
       (other than $0) are set.  This is a difference from the way other func‐
       tions are parsed: normal function definitions may be followed  by  cer‐
       tain  keywords  such  as `else' or `fi', which will be treated as argu
       ments to anonymous functions, so that a newline or semicolon is  needed
       to force keyword interpretation.

       Note also that the argument list of any enclosing script or function is
       hidden (as would be the case for any  other  function  called  at  this
       point).

       Redirections  may be applied to the anonymous function in the same man
       ner as to a current-shell structure enclosed in braces.  The  main  use
       of anonymous functions is to provide a scope for local variables.  This
       is particularly convenient in start-up files as these  do  not  provide
       their own local variable scope.

       For example,

              variable=outside
              function {
                local variable=inside
                print "I am $variable with arguments $*"
              } this and that
              print "I am $variable"

       outputs the following:

              I am inside with arguments this and that
              I am outside

       Note  that  function definitions with arguments that expand to nothing,
       for example `name=; function $name { ... }', are not treated as  anony‐
       mous  functions.   Instead, they are treated as normal function defini‐
       tions where the definition is silently discarded.

Mas, além disso - se você não estiver usando a exportsua .zshrc, a variável deve estar visível apenas na sua sessão interativa atual e não deve ser exportada para subshells.

Como Terdon explicou em seu comentário: export -nin bashapenas faz com que a propriedade "export" seja removida da variável, portanto, usar export -n GREP_OPTIONS=--color=alwaysé equivalente a não usar exportação de todo - GREP_OPTIONS=--color=always.

Em outras palavras, para obter o comportamento desejado, simplesmente não use export. Em vez disso, .zshrcvocê deve ter

GREP_OPTIONS=--color=always

Isso tornará a variável disponível para todos os shells (interativos, sem logon) que você executar, exatamente como você deseja, mas não será exportada para shells filhos.

Martin von Wittich
fonte
Apenas ter GREP_OPTIONS = - color = always "é o que estou fazendo, como mostrado na minha pergunta. Outra coisa no zsh está fazendo com que todas as minhas variáveis ​​sejam exportadas automaticamente. Ainda estou tentando descobrir o que é isso.
PonyEars