Как распечатать только что настроенную переменную среды?
NAME=sam echo "$NAME" # empty
Вы можете увидеть здесь, используя eval, он работает. Так ли это?
NAME=sam eval 'echo $NAME' # => sam
Как распечатать только что настроенную переменную среды?
NAME=sam echo "$NAME" # empty
Вы можете увидеть здесь, используя eval, он работает. Так ли это?
NAME=sam eval 'echo $NAME' # => sam
Они должны идти как разные команды, например:
NAME=sam; echo "$NAME"
NAME=sam && echo "$NAME"
Расширение $NAME в пустую строку выполняется оболочкой раньше, перед запуском echo, поэтому в то время, когда переменная NAME передается в среду команд командной строки echo, расширение уже выполнено (для null string).
Чтобы получить тот же результат в одной команде:
NAME=sam printenv NAME
Чтобы привести существующие ответы вместе с важным разъяснением:
Как уже говорилось, проблема с NAME=sam echo "$NAME" заключается в том, что $NAME расширяется текущей оболочкой до того, как назначение NAME=sam вступит в силу.
Решения, которые сохраняют исходную семантику ((неэффективной) попытки решения NAME=sam echo "$NAME"):
Используйте либо eval [1] (как в самом вопросе), либо printenv (как добавлено Аароном МакДейдом к ответу на вопрос), либо bash -c (из ответа Ljm Dullaart) в порядке убывания эффективности:
NAME=sam eval 'echo "$NAME"' # use 'eval' only if you fully control the command string
NAME=sam printenv NAME
NAME=sam bash -c 'echo "$NAME"'
printenv - это не утилита POSIX, но она доступна как для Linux, так и для macOS/BSD.
Что этот стиль вызова (<var>=<name> cmd...) делает для определения NAME:
Другими словами: NAME существует только для вызываемой команды и не влияет на текущую оболочку (если до этого не существовало никакой переменной с именем NAME после не будет ни одной; существующая переменная NAME остается неизменной).
POSIX определяет правила для такого рода вызовов в главе " Поиск и выполнение команд".
Следующие решения работают совсем по-другому (от ответа heemayl):
NAME=sam; echo "$NAME"
NAME=sam && echo "$NAME"
Хотя они выдают одинаковый результат, они вместо этого определяют:
NAME (только), а не переменная окружения echo была командой, использующей переменную окружения NAME, она не была бы определена (или потенциально определена иначе, чем ранее). Обратите внимание, что каждая переменная среды также отображается как переменная оболочки, но обратное неверно: переменные оболочки видны только текущей оболочке и ее подоболочкам, но не дочерним процессам, таким как внешние утилиты и (неисследованные) сценарии. (если только они не помечены как переменные окружения с помощью export или declare -x).
[1] Технически, bash здесь нарушает POSIX (как и zsh): поскольку eval - это специальная встроенная оболочка, предыдущее назначение NAME=sam должно привести к тому, что переменная $NAME останется в области действия после завершения команды, но это не то, что происходит.
Однако, когда вы запускаете bash в режиме совместимости с POSIX, он совместим.dash и ksh всегда соответствуют.
Точные правила сложны, и некоторые аспекты оставлены на усмотрение реализаций;снова см. Поиск и выполнение команд.
Кроме того, применяется обычный отказ от ответственности: используйте eval только в тех случаях, когда вы полностью контролируете или неявно доверяете.
Это тоже работает с помощью двоеточия.
NAME=sam; echo $NAME
Синтаксис
variable=value command
часто используется для установки переменных среды для определенного процесса. Однако вы должны понять, какой процесс получает переменную и кто ее интерпретирует. В качестве примера, используя две оболочки:
a=5
# variable expansion by the current shell:
a=3 bash -c "echo $a"
# variable expansion by the second shell:
a=3 bash -c 'echo $a'
Результат будет 5 для первого эха и 3 для второго.