Замена имен переменных оболочки в другой переменной

Я уже некоторое время занимаюсь борьбой с заменой переменных bash и не могу понять это …

У меня есть переменная с шаблоном команды:

 CMD_TMPL='sudo -u ${USER_NAME} ${USER_HOME}/script.sh' 

Переменные USER_NAME и USER_HOME позже в скрипте, еще не известном в то время, CMD_TMPL определено CMD_TMPL . Поэтому команда находится в одинарных кавычках, и они еще не заменены.

Затем сценарий USER_HOME=/home/test USER_NAME=test и USER_HOME=/home/test и я хочу сделать что-то, что приведет к ${CMD} содержащему:

 sudo -u test /home/test/script.sh 

Далее в сценарии я буду использовать эту команду в канале, например:

 ${CMD} | output-processing.sh 

Как достичь расширения от имен переменных в ${CMD_TMPL} до значений переменных в ${CMD} ? Я пробовал всевозможные echo и eval , но не могу понять.

Благодаря!

Существует специальный тип переменной, который используется для хранения кода, это функции :

 cmd_tmpl() { sudo -u "$USER_NAME" "$USER_HOME/script.sh" "$@"; } cmd() { cmd_tmpl other args "$@"; } cmd | output_processing... 

Другие подходы – рассматривать переменные как командные строки (код оболочки) и интерпретировать этот код в конце с помощью eval :

 cmd_tmpl='sudo -u "$USER_NAME" "$USER_HOME/script.sh"' cmd=$cmd_tmpl' other args as shell code' eval "$cmd" | output_processing... 

Использование $cmd | output_processing $cmd | output_processing неверно. $cmd – это скалярные переменные, и вы используете оператор split + glob для получения списка аргументов простой команде, вы не оцениваете сохраненную в ней командную строку. Так что работает только в ограниченном наборе условий.

Вы можете хранить аргументы в простой команде в массиве:

 cmd=(sudo -u "$USER_NAME" "$USER_HOME/script.sh" ...) "${cmd[@]}" | post_processing 

но это не поможет с отсроченным расширением ваших переменных.

Вы можете отложить расширение, но с такими вещами, как:

 cmd_tmpl='sudo -u "$USER_NAME" "$USER_HOME/script.sh"' ... eval "cmd=($cmd_tmpl)" # now expanded cmd+=(other args) "${cmd[@]}" | post-processing 

(учтите, что рекомендуется сохранять все имена переменных верхнего регистра для переменных, экспортируемых в среду).