Как распечатать только что настроенную переменную среды?
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 для второго.