Якщо я біжу
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
отримання TEST
env 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
.