При написании кода я обнаружил, что эта строка:
$ TZ="America/Los_Angeles" date; echo "$TZ"
Thu Dec 24 14:39:15 PST 2015
Правильно показывает фактическое время в «Лос-Анджелесе» и то, что значение переменной TZ
не сохраняется. Все как и следовало ожидать.
Однако с этой строкой, которую я использовал для расширения некоторых форматов до настоящего времени и которая по сути выполняет то же самое, сохраняется значение TZ:
TZ="America/Los_Angeles" eval date; echo "$TZ"
Thu Dec 24 14:41:34 PST 2015
America/Los_Angeles
После еще нескольких тестов я обнаружил, что это происходит только в некоторых оболочках. Это происходит в dash, ksh, но не в bash или zsh.
Q-х
Вопрос (ы):
- Почему значение TZ сохраняется в настоящей оболочке?
- Как этого можно избежать / контролировать (если это возможно)?
Дополнительно.
Я провел тесты в нескольких оболочках с этими двумя строками:
myTZ="America/Los_Angeles"
unset TZ; { TZ="$myTZ" date; } >/dev/null; echo -n " direct $TZ"
unset TZ; { TZ="$myTZ" eval date; } >/dev/null; echo " evaled $TZ"
И это приводит к:
/bin/ash : direct evaled America/Los_Angeles
/bin/dash : direct evaled America/Los_Angeles
/bin/sh : direct evaled America/Los_Angeles
/bin/bash : direct evaled
/bin/ksh93 : direct evaled America/Los_Angeles
/bin/lksh : direct evaled America/Los_Angeles
/bin/mksh : direct evaled America/Los_Angeles
/bin/zsh : direct evaled
/bin/zsh4 : direct evaled
Значение TZ влияет на работающую оболочку во всех оболочках, кроме bash и zsh.
Оказывается, есть очень специфическая причина для такого поведения.
Описание того, что происходит, немного длиннее.
Только задания.
Командная строка, выполненная (только) из назначений, установит переменные для этой оболочки.
Значение присвоенных переменных будет сохранено.
Внешняя команда.
Назначения перед внешней командой устанавливают переменные только для этой оболочки:
И я имею в виду «внешнюю» как любую команду, которую нужно искать в PATH.
Это также относится к обычным встроенным модулям (например, cd):
До сих пор все как обычно ожидается.
Специальные встроенные модули.
Но для специальных встроенных функций POSIX требует, чтобы значения были установлены для этой оболочки .
Я использую вызов, чтобы
sh
предположить, чтоsh
это POSIX-совместимая оболочка.Это не то, что обычно используется.
Это означает, что назначения, расположенные перед любым из этого списка специальных встроенных модулей, должны сохранять назначенные значения в текущей работающей оболочке:
Это произойдет, если оболочка работает согласно спецификации POSIX.
Вывод:
Можно установить переменные только для одной команды, любой команды, убедившись, что команда не является специальной встроенной. Команда
command
является обычным встроенным. Он только говорит оболочке использовать команду, а не функцию. Эта строка работает во всех оболочках (кроме ksh93):В таком случае переменные a и b устанавливаются для среды команды команды и после этого отбрасываются.
Вместо этого это сохранит присвоенные значения (кроме bash и zsh):
Обратите внимание, что присвоение после eval заключено в одинарные кавычки, чтобы защитить его от нежелательных расширений.
Итак: Для размещения переменных в командной среде используйте
command eval
:источник