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

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

export PLACEHOLDER1="myPlaceholder1Value"
sudo /bin/su -c "cat << EOF > /etc/init.d/my-script
#!/bin/bash

myvariable_1=toto$PLACEHOLDER1
myvariable_final=\"dynamicvar=\${myvariable_1},\${myvariable_2}\"
EOF
"

Это приводит к тому, что это нехорошо, так как myvariable_final не экранируется и подставляется из зависимостей скрипта инициализации ($remote_fs, $syslog, $network, $time)

#!/bin/bash

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

myvariable_1=toto$PLACEHOLDER1
myvariable_2=titi$PLACEHOLDER2
myvariable_final=\"dynamicvar=\$\{myvariable_1},\$\{myvariable_2}\"
EOF
"

приводит к:

#!/bin/bash

myvariable_1=totomyPlaceholder1Value
myvariable_2=titimyPlaceholder2Value
myvariable_final="dynamicvar=$\{myvariable_1},$\{myvariable_2}"

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

#!/bin/bash

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

myvariable_1=toto$PLACEHOLDER1
myvariable_2=titi$PLACEHOLDER2
myvariable_final=\"dynamicvar=\${myvariable_1},\${myvariable_2}\"
EOF
"

person TheCodeKiller    schedule 13.01.2015    source источник
comment
обратите внимание, что только первый «EOF» нуждается в кавычках!   -  person masterxilo    schedule 20.11.2018
comment
если вы используете «EOF» с кавычками, это не заменит, но, например, в моем случае мне нужно заменить какую-то переменную, а некоторые переменные env не экранировать. Как мы это делаем.   -  person indianwebdevil    schedule 23.12.2020


Ответы (2)


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

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

От man bash:

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

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

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

      <<[-]word
              here-document
      delimiter

Для слова не выполняется расширение параметров, подстановка команд, арифметическое расширение или расширение имени пути. Если какие-либо символы в слове заключены в кавычки, разделитель является результатом удаления кавычек в слове, а строки в здесь-документе не расширяются. Если слово не заключено в кавычки, все строки здесь-документа подвергаются расширению параметров, подстановке команд и арифметическому расширению. В последнем случае последовательность символов \<newline> игнорируется, а \ необходимо использовать для кавычек символов \, $ и `.

person fedorqui 'SO stop harming'    schedule 13.01.2015
comment
Цитата вокруг «EOF» сделала свое дело, как и при побеге, я могу контролировать, что заменяется, а wnat не заменяется - person TheCodeKiller; 13.01.2015

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

su -c 'ph="ph"; cat << EOF > script 
varinscript=$ph
var=\${var}
EOF'
person Marc Bredt    schedule 13.01.2015
comment
Ваш ответ в порядке, но я хочу предотвратить повторный ввод всех env/export VAR в команду. - person TheCodeKiller; 13.01.2015
comment
так что не нужно цитировать EOF в этом случае? - person Walid; 29.06.2019