Если я бегу
export TEST=foo
echo $TEST
Это выводит foo.
Если я бегу
TEST=foo echo $TEST
Это не. Как я могу получить эту функциональность без использования экспорта или сценария?
Если я бегу
export TEST=foo
echo $TEST
Это выводит foo.
Если я бегу
TEST=foo echo $TEST
Это не. Как я могу получить эту функциональность без использования экспорта или сценария?
Ответы:
Это связано с тем, что оболочка раскрывает переменную в командной строке до того, как она фактически запускает команду, и в то время переменная не существует. Если вы используете
TEST=foo; echo $TEST
это будет работать.
export
заставит переменную появиться в среде впоследствии выполненных команд (см help export
., как это работает в bash ). Если вам нужно, чтобы переменная появлялась только в среде одной команды, используйте то, что вы пробовали, т.е.
TEST=foo your-application
$TEST
перед выполнением командной строки. После того, echo
как выполняется (также обратите внимание, что echo
это обычно переводится во встроенную команду оболочки, а не в /bin/echo
), она видит набор переменных в своей среде. Однако echo $TEST
не говорит echo
выводить содержимое переменной TEST
из ее окружения. Он говорит оболочке запускаться echo
с аргументом, который в настоящее время находится в переменной, называемой TEST
- и это две совершенно разные вещи.
var=value sh -c 'echo "$var"'
?
"… $var …"
), но не внутри одинарных кавычек (например, '… $var …'
). Поскольку echo "$var"
внутри одиночных кавычек, вся строка передается в sh -c
оболочку new ( ) без интерпретации внешней интерактивной оболочкой. … (Продолжение)
sh -c
дочерней оболочкой new ( ).
Я подозреваю, что вы хотите, чтобы переменные оболочки имели ограниченную область видимости, а не переменные среды. Переменные среды представляют собой список строк, передаваемых командам при их выполнении .
В
var=value echo whatever
Вы передаете var=value
строку в среду, которую получает эхо. Тем echo
не менее, ничего не делает со своим списком окружения и, в любом случае, в большинстве оболочек echo
он встроен и поэтому не выполняется .
Если бы вы написали
var=value sh -c 'echo "$var"'
Это было бы другое дело. Здесь мы проходим var=value
к sh
команде, и sh
случается использовать его окружение. Оболочки преобразуют каждую из переменных, которые они получают из своей среды, в переменную оболочки, поэтому полученные var
переменные среды sh
будут преобразованы в $var
переменную, и когда она развернет ее в этой echo
командной строке, это станет echo value
. Поскольку среда по умолчанию наследуется, echo
она также получает var=value
в своей среде (или получит, если бы она была выполнена), но, опять же, echo
не заботится об окружающей среде.
Теперь, если, как я подозреваю, вам нужно ограничить область действия переменных оболочки, есть несколько возможных подходов.
Портативно (Борн и POSIX):
(var=value; echo "1: $var"); echo "2: $var"
(...) выше запускает под-оболочку (новый процесс оболочки в большинстве оболочек), поэтому любая объявленная там переменная будет влиять только на эту под-оболочку, поэтому я ожидаю, что приведенный выше код выведет «1: значение» и «2:» или «2: все, что было установлено ранее».
С большинством Bourne-подобных оболочек вы можете использовать функции и встроенную «локальную» функцию:
f() {
local var
var=value
echo "1: $var"
}
f
echo "2: $var"
С zsh вы можете использовать встроенные функции:
(){ local var=value; echo "1: $var"; }; echo "2: $var"
или же:
function { local var=value; echo "1: $var"; }; echo "2: $var"
С bash и zsh (но не с ash, pdksh или AT & T ksh) этот прием также работает:
var=value eval 'echo "1: $var"'; echo "2: $var"
Вариант , который работает в течение еще нескольких оболочек ( dash
, mksh
, yash
) , но не zsh
(если в sh
/ ksh
эмуляции):
var=value command eval 'echo "1: $var"'; echo "2: $var"
(использование command
перед встроенным (здесь eval
) в оболочках POSIX исключает их особенность (здесь присваивание переменных из них остается в силе после их возвращения))
Вы делаете это правильно, но синтаксис bash легко неверно истолковать: вы можете подумать, что echo $TEST
приводит echo
к извлечению TEST
env var, а затем распечатывает его, а это не так. Так дано
export TEST=123
тогда
TEST=456 echo $TEST
включает в себя следующую последовательность:
Оболочка анализирует всю командную строку и выполняет все подстановки переменных, поэтому командная строка становится
TEST=456 echo 123
Он создает временные переменные, установленные перед командой, поэтому сохраняет текущее значение TEST
и перезаписывает его с помощью 456; командная строка сейчас
echo 123
Он выполняет оставшуюся команду, которая в этом случае печатает 123 в стандартный вывод (так что оставшаяся команда оболочки даже не использовала временное значение TEST
)
Восстанавливает ценность TEST
Вместо этого используйте printenv, поскольку он не требует подстановки переменных:
>> export TEST=123
>> printenv TEST
123
>> TEST=456 printenv TEST
456
>> printenv TEST && TEST=456 printenv TEST && TEST=789 printenv TEST && printenv TEST
123
456
789
123
>>
printenv
полезным для тестирования / доказательства концепции (ведет себя как сценарий, а не как echo
)
Вы можете получить это с помощью:
TEST=foo && echo $TEST
TEST=foo
выполняется как отдельный оператор - он не просто устанавливается в контексте echo
.