Если я бегу
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к извлечению TESTenv 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.