Локальные переменные в zsh: что эквивалентно bash «export -n» в zsh

10

Я пытаюсь содержать область видимости переменной в оболочке, а дети не видят ее в zsh. Например, я набираю это в .zshrc:

GREP_OPTIONS=--color=always

Но если я запускаю скрипт оболочки со следующим:

#!/bin/bash
echo $GREP_OPTIONS

Выход:

--color=always

в то время как я хочу, чтобы он был нулевым (скрипт выше не должен видеть переменную GREP_OPTIONS).

В bash можно сказать export -n GREP_OPTIONS=--color=always, что это не допустит. Как мне сделать это в Zsh?

PonyEars
источник
1
export -nпросто экспортирует экспортированную переменную.
Terdon

Ответы:

11

exportв zsh это сокращение для typeset -gx, где атрибут gозначает «глобальный» (в отличие от локального для функции), а атрибут xозначает «экспортированный» (то есть в среде). Таким образом:

typeset +x GREP_OPTIONS

Это также работает в ksh и bash.

Если вы никогда не экспортируете GREP_OPTIONSв первую очередь, вам не нужно экспортировать его.

Вы также можете использовать косвенный переносимый способ: сброс переменной отменяет ее экспорт. В ksh / bash / zsh это не работает, если переменная доступна только для чтения.

tmp=$GREP_OPTIONS
unset GREP_OPTIONS
GREP_OPTIONS=$tmp
Жиль "ТАК - перестань быть злым"
источник
Смотрите также env -u GREP_OPTIONS your-scriptс некоторыми envреализациями (любая оболочка). Или(unset GREP_OPTIONS; exec your-script)
Стефан Шазелас
Я пробовал набирать + x, но это тоже не имеет значения. Как показано в моем вопросе, что-то экспортирует все переменные, которые я определяю, даже если я не включаю «экспорт». Все еще пытаюсь выяснить почему.
PonyEars
@redstreet Может быть, вы случайно установили опцию export_all( -a)? Но даже тогда typeset +x GREP_OPTIONSбы не экспортировать переменную. Если вы не можете найти, что не так, попробуйте бинарный поиск: создайте резервную копию .zshrc, удалите вторую половину, посмотрите, не возникла ли проблема, затем добавьте третий квартал или сократите до первого квартала и повторите.
Жиль "ТАК ... перестать быть злым"
@ Жиль Спасибо, я нашел это: у zsh есть опция "allexport", которая была у меня в .zshrc. «setopt noallexport» может временно отключить его, если это поможет кому-либо еще. Я приму ваш ответ, так как он пришел ближе всего.
PonyEars
Теперь у меня есть другая проблема, которая ближе к проблеме, которую я пытаюсь решить, здесь: unix.stackexchange.com/questions/113645/…
PonyEars
6

Вы можете использовать анонимную функцию для предоставления области видимости для переменной. От 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.

Но кроме этого - если вы не используете exportв вашем .zshrcвообще, переменная должна быть видна только в текущей интерактивной сессии, и она не должна быть экспортирована в подоболочек.

Как пояснил в своем комментарии terdon: export -nin bashпросто приводит к удалению свойства «export» из переменной, поэтому использование export -n GREP_OPTIONS=--color=alwaysэквивалентно тому, что экспорт вообще не используется - GREP_OPTIONS=--color=always.

Другими словами, чтобы получить желаемое поведение, просто не используйте export. Вместо этого в вашем .zshrc, вы должны иметь

GREP_OPTIONS=--color=always

Это сделает переменную доступной для всех оболочек (интерактивных, без входа в систему), которые вы запускаете, так же, как вы этого хотите, но она не будет экспортирована в дочерние оболочки.

Мартин фон Виттих
источник
Просто наличие GREP_OPTIONS = - color = всегда "- это то, что я делаю, как показано в моем вопросе. Что-то еще в zsh заставляет все мои переменные автоматически экспортироваться. Все еще пытаюсь выяснить, что это такое.
PonyEars