У вас опечатка. Вам не хватает $
перед(which npm)
Так ты хочешь$(which npm)
Структура $(...)
означает «запустить команду внутри скобок и вернуть результат»
declare
(как и typeset
других оболочек; также понимается как bash
как псевдоним для declare
), объявляет переменную в текущей области видимости (и может устанавливать тип и/или значение ).
Итак, здесь вы должны объявить переменную, которая является локальной для функции create_variable_for_arch
. Когда эта функция вернется, эта переменная исчезнет.
bash
's declare
/ typeset
имеет опцию -g
для объявления переменной глобальной ), но вы также не можете использовать ее, поскольку она объявляет переменную (и устанавливает ее тип и/или значение )во внешней -наибольшей области действия, в отличие от области действия вызывающей функции, поэтому там довольно бесполезно (, оно более полезно в mksh
/ zsh
/ yash
где он только пропускает , делая его локальным или с ksh93, который имеет статическую область видимости, см. . Что делают `объявлять имя `и `объявлять -g `? подробнее ).
Таким образом, вы можете либо использовать eval
, либо использовать namerefs :
create_variable_for_arch() {
if [ "$_run_for_arch" = mac ]; then
eval "$1=\$2"
else
eval "$1=\$3"
fi
}
Или, предполагая, что $_run_for_arch
является константой в вашем скрипте:
if [ "$_run_for_arch" = "mac" ]; then
create_variable_for_arch() { eval "$1=\$2"; }
else
create_variable_for_arch() { eval "$1=\$3"; }
fi
Или с именами:
create_variable_for_arch() {
typeset -n _var_name="$1"
if [ "$_run_for_arch" = mac ]; then
_var_name=$2
else
_var_name=$3
fi
}
Часто (справедливо )рекомендуется избегать eval
из соображений безопасности, но eval
безопасен при правильном использовании. declare
и namerefs
были бы здесь небезопасны при неправильном использовании, поскольку они оба могут также оценивать код.
Все:
f() { eval "$1=\$2"; }
f() { declare "$1=$2"; }
f() { declare -n v="$1"; v=$2; }
Будет выполняться команда reboot
, если она вызывается с:
f 'a[$(reboot)]' value
Важно убедиться, что первым аргументом является имя переменной, чтобы избежать уязвимости, связанной с выполнением произвольной команды.
f() { declare $1=$2; }
было бы гораздо хуже. Поскольку эти расширения параметров не заключены в кавычки, они подлежат разделению + подстановке, поэтому даже содержимое $2
может в конечном итоге оцениваться как шелл-код, как в:
f var 'foo a[$(reboot)]='