Zmienne lokalne w zsh: co jest odpowiednikiem „export -n” bash w zsh

10

Próbuję zawrzeć zakres zmiennej w powłoce i nie chcę, aby dzieci widziały go w Zsh. Na przykład wpisuję to w .zshrc:

GREP_OPTIONS=--color=always

Ale jeśli uruchomię skrypt powłoki z następującymi elementami:

#!/bin/bash
echo $GREP_OPTIONS

Dane wyjściowe to:

--color=always

podczas gdy chcę, aby była zerowa (powyższy skrypt powłoki nie powinien w ogóle widzieć zmiennej GREP_OPTIONS).

W bashu można powiedzieć:, export -n GREP_OPTIONS=--color=alwaysco temu zapobiec. Jak to zrobić w Zsh?

PonyEars
źródło
1
export -npo prostu nie eksportuje eksportowanej zmiennej.
terdon

Odpowiedzi:

11

exportw zsh jest skrótem typeset -gx, gdzie atrybut goznacza „globalny” (w przeciwieństwie do lokalnego dla funkcji), a atrybut xoznacza „wyeksportowany” (tj. w środowisku). A zatem:

typeset +x GREP_OPTIONS

Działa to również w ksh i bash.

Jeśli nigdy nie eksportujesz GREP_OPTIONS, nie musisz go cofać.

Możesz także użyć pośredniego, przenośnego sposobu: rozbrojenie zmiennej nie powoduje jej wyeksportowania. W ksh / bash / zsh to nie działa, jeśli zmienna jest tylko do odczytu.

tmp=$GREP_OPTIONS
unset GREP_OPTIONS
GREP_OPTIONS=$tmp
Gilles „SO- przestań być zły”
źródło
Zobacz także env -u GREP_OPTIONS your-scriptniektóre envimplementacje (dowolna powłoka). Lub(unset GREP_OPTIONS; exec your-script)
Stéphane Chazelas
Próbowałem typeset + x, ale to też nie robi różnicy. Jak pokazano w moim pytaniu, coś eksportuje wszystkie zmienne, które zdefiniuję, nawet jeśli nie uwzględniam „eksport”. Wciąż próbuję dowiedzieć się, dlaczego.
PonyEars,
@redstreet Może przypadkowo ustawiłeś opcję export_all( -a)? Ale nawet wtedy typeset +x GREP_OPTIONSwyeksportuje zmienną. Jeśli nie możesz znaleźć, co jest nie tak, spróbuj wyszukać binarnie: zrób kopię zapasową .zshrc, usuń drugą połowę, sprawdź, czy problem nadal występuje, następnie dołącz trzeci kwartał lub zmniejsz go do pierwszego kwartału i powtórz.
Gilles „SO- przestań być zły”
@Gilles Dzięki, znalazłem to: zsh ma opcję „allexport”, którą miałem w moim .zshrc. „setopt noallexport” może go tymczasowo wyłączyć, jeśli pomoże komukolwiek innemu. Przyjmę twoją odpowiedź, ponieważ była najbliższa.
PonyEars,
Teraz mam inny problem, który jest bliższy problemowi, który próbuję rozwiązać, tutaj: unix.stackexchange.com/questions/113645/…
PonyEars
6

Możesz użyć funkcji anonimowej, aby zapewnić zakres dla zmiennej. Od 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.

Ale poza tym - jeśli nie używasz exportw swojej .zshrcw ogóle, zmienna powinny być widoczne tylko w bieżącej sesji interaktywnej, i nie powinny być eksportowane do podpowłok.

Jak wyjaśnił terdon w swoim komentarzu: export -npo bashprostu powoduje, że właściwość „export” jest usuwana ze zmiennej, więc użycie export -n GREP_OPTIONS=--color=alwaysjest równoznaczne z całkowitym niestosowaniem eksportu - GREP_OPTIONS=--color=always.

Innymi słowy, aby uzyskać pożądane zachowanie, po prostu nie używaj export. Zamiast tego .zshrcpowinieneś mieć

GREP_OPTIONS=--color=always

Dzięki temu zmienna będzie dostępna dla wszystkich uruchomionych powłok (interaktywnych, niezalogowanych), dokładnie tak, jak chcesz, ale nie zostanie wyeksportowana do powłok potomnych.

Martin von Wittich
źródło
Po prostu posiadanie GREP_OPTIONS = - color = always "jest tym, co robię, jak pokazano w moim pytaniu. Coś innego w zsh powoduje, że wszystkie moje zmienne są eksportowane automatycznie. Wciąż próbuję dowiedzieć się, co to jest.
PonyEars