Подтвердить что ты не робот

Как избежать переменных расширения heredoc?

Я пытаюсь создать файл script, используя строку подстановки из ENV, но также хочу, чтобы некоторые из них не выполнялись

export PLACEHOLDER1="myPlaceholder1Value"
export PLACEHOLDER2="myPlaceholder2Value"
sudo /bin/su -c "cat << EOF > /etc/init.d/my-script
#!/bin/bash
#
### BEGIN INIT INFO
# Provides:          my-script
# Required-Start:    \$remote_fs \$syslog
# Required-Stop:     \$remote_fs \$syslog
# Should-Start:      \$network \$time
# Should-Stop:       \$network \$time
# Default-Start:     2 3 4 5 
# Default-Stop:      0 1 6
# Short-Description: blabla
# Description:       bla bla desc
#
### END INIT INFO
#
myvariable_1=toto$PLACEHOLDER1
myvariable_2=titi$PLACEHOLDER2
myvariable_final=\"dynamicvar=\${myvariable_1},\${myvariable_2}\"
EOF
"

В результате это не так хорошо, поскольку myvariable_final не экранируются и не заменяются как зависимые от инициализационных script ($ remote_fs, $syslog, $network, $time)

#!/bin/bash
#
### BEGIN INIT INFO
# Provides:          my-script
# Required-Start:
# Required-Stop:
# Should-Start:
# Should-Stop:
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: blabla
# Description:       bla bla desc
#
### END INIT INFO
#
myvariable_1=totomyPlaceholder1Value
myvariable_2=titimyPlaceholder2Value
myvariable_final="dynamicvar=,"

Если я попытаюсь поместить обратную косую черту \ за доллары $, мне удастся избежать подстановки, но я получаю нежелательную обратную косую черту \:

export PLACEHOLDER1="myPlaceholder1Value"
export PLACEHOLDER2="myPlaceholder2Value"
sudo /bin/su -c "cat << EOF > /etc/init.d/my-script
#!/bin/bash
#
### BEGIN INIT INFO
# Provides:          my-script
# Required-Start:    \$\remote_fs \$\syslog
# Required-Stop:     \$remote_fs \$syslog
# Should-Start:      \$network \$time
# Should-Stop:       \$network \$time
# Default-Start:     2 3 4 5 
# Default-Stop:      0 1 6
# Short-Description: blabla
# Description:       bla bla desc
#
### END INIT INFO
#
myvariable_1=toto$PLACEHOLDER1
myvariable_2=titi$PLACEHOLDER2
myvariable_final=\"dynamicvar=\$\{myvariable_1},\$\{myvariable_2}\"
EOF
"

приводит к:

#!/bin/bash
#
### BEGIN INIT INFO
# Provides:          my-script
# Required-Start:    $\remote_fs $\syslog
# Required-Stop:
# Should-Start:
# Should-Stop:
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: blabla
# Description:       bla bla desc
#
### END INIT INFO
#
myvariable_1=totomyPlaceholder1Value
myvariable_2=titimyPlaceholder2Value
myvariable_final="dynamicvar=$\{myvariable_1},$\{myvariable_2}"

Требуемый/посещаемый результат, который был:

#!/bin/bash
#
### BEGIN INIT INFO
# Provides:          my-script
# Required-Start:    $remote_fs $syslog
# Required-Stop:     $remote_fs $syslog
# Should-Start:      $network $time
# Should-Stop:       $network $time
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: blabla
# Description:       bla bla desc
#
### END INIT INFO
#
myvariable_1=totomyPlaceholder1Value
myvariable_2=titimyPlaceholder2Value
myvariable_final="dynamicvar=${myvariable_1},${myvariable_2}"

решив поставить цитату вокруг EOF, как показано ниже, и использовать обратную косую черту для управления экранированием при необходимости

export PLACEHOLDER1="myPlaceholder1Value"
export PLACEHOLDER2="myPlaceholder2Value"
sudo /bin/su -c "cat << 'EOF' > /etc/init.d/my-script
#!/bin/bash
#
### BEGIN INIT INFO
# Provides:          my-script
# Required-Start:    \$remote_fs \$syslog
# Required-Stop:     \$remote_fs \$syslog
# Should-Start:      \$network \$time
# Should-Stop:       \$network \$time
# Default-Start:     2 3 4 5 
# Default-Stop:      0 1 6
# Short-Description: blabla
# Description:       bla bla desc
#
### END INIT INFO
#
myvariable_1=toto$PLACEHOLDER1
myvariable_2=titi$PLACEHOLDER2
myvariable_final=\"dynamicvar=\${myvariable_1},\${myvariable_2}\"
EOF
"
4b9b3361

Ответ 1

Просто используйте 'EOF', чтобы предотвратить расширение переменной:

sudo /bin/su -c "cat << 'EOF' > /etc/init.d/my-script
#                       ^   ^

От man bash:

Здесь Документы

Этот тип перенаправления инструктирует оболочку читать входные данные из тока, пока строка, содержащая только разделитель (без завершающие пробелы). Все строки, прочитанные до этого, являются затем используется как стандартный ввод для команды.

Формат здесь-документов:

      <<[-]word
              here-document
      delimiter

Нет расширения параметров, подстановки команд, арифметического расширения, или расширение имени пути выполняется по слову. Если какие-либо символы в слове цитируются, разделитель является результатом удаления цитаты на слове и строки в этом документе не расширены. Если слово unquoted, все строки здесь-документа подвергаются параметру расширение, подстановку команд и арифметическое расширение. в в последнем случае последовательность символов\игнорируется, а \ должен использоваться для цитирования символов \, $и `.

Ответ 2

при использовании команды su поместите эту команду в кавычки sigle и просто выйдите из $с обратным слэшем. переменные-заполнители должны установить команду bash context (здесь после su). поэтому вам нужно сделать что-то вроде

su -c 'ph="ph"; cat << EOF > script 
varinscript=$ph
var=\${var}
EOF'