Якщо я біжу
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зробить змінну з'являтися в середовищі згодом виконаних команд (про те, як це працює в bash див. help export). Якщо вам потрібна лише змінна для відображення в середовищі однієї команди, використовуйте те, що ви спробували, тобто:
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) оболонці без інтерпретації зовнішньої, інтерактивної оболонки. … (Продовження)
sh -c) дочірньою оболонкою.
Я підозрюю, що ви хочете, щоб змінні оболонки мали обмежений діапазон, а не змінні середовища. Змінні середовища - це список рядків, переданих командам при їх виконанні .
В
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це не хвилює оточення.
Тепер, якщо я підозрюю, що ви хочете обмежити область змінних оболонок, існує кілька можливих підходів.
Портативно (Bourne та POSIX):
(var=value; echo "1: $var"); echo "2: $var"
Вище (...) запускає підзагін (новий процес оболонки в більшості оболонок), тому будь-яка змінна заявлена там буде впливати лише на цю під оболонку, тож я очікую, що код вище виведе "1: значення" і "2:" або "2: все, що було варі-було встановлено раніше".
У більшості оболонок, подібних до Борна, ви можете використовувати функції та "локальний" вбудований:
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 (але не золом, 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 в stdout (так що команда оболонки, що залишається, навіть не використовувала значення temp 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.