Использование переменных внутри bash heredoc
Я пытаюсь интерполировать переменные внутри bash heredoc:
var=$1
sudo tee "/path/to/outfile" > /dev/null << "EOF"
Some text that contains my $var
EOF
Это не работает, как я ожидал ($ var обрабатывается буквально, а не расширяется).
Мне нужно использовать sudo tee, потому что для создания файла требуется sudo. Выполнение чего-то вроде:
sudo cat > /path/to/outfile <<EOT
my text...
EOT
Не работает, потому что > outfile открывает файл в текущей оболочке, которая не использует sudo.
Ответы
Ответ 1
В ответ на ваш первый вопрос нет замены параметров, потому что вы помещаете разделитель в кавычки - в руководстве bash говорится:
Формат здесь-документов:
<<[-]word
here-document
delimiter
Нет расширения параметров, подстановки команд, арифметического расширения или расширение имени пути выполняется по слову. Если любые символы в слове цитируемый, разделитель является результатом удаления цитаты на слове, а строки в этом документе не будут расширены. Если слово без кавычек, все строки этого документа подвергаются расширению параметров, подстановке команд и арифметическому расширению. [...]
Если вы изменили свой первый пример на использование <<EOF
вместо << "EOF"
, вы обнаружите, что он работает.
В вашем втором примере оболочка вызывает sudo
только с параметром cat
, и перенаправление применяется к выходу sudo cat
в качестве исходного пользователя. Он будет работать, если вы попробуете:
sudo sh -c "cat > /path/to/outfile" <<EOT
my text...
EOT
Ответ 2
Не используйте кавычки с <<EOF
:
var=$1
sudo tee "/path/to/outfile" > /dev/null <<EOF
Some text that contains my $var
EOF
Переменное расширение - это поведение по умолчанию внутри here-docs. Вы отключите это поведение, указав метку (с одинарными или двойными кавычками).
Ответ 3
Как поздний вывод из предыдущих ответов, вы, вероятно, окажетесь в ситуациях, когда вы хотите, чтобы некоторые, но не все переменные были интерполированы. Вы можете решить эту проблему, используя обратную косую черту, чтобы избежать знаков доллара и обратных кавычек; или вы можете поместить статический текст в переменную.
Name='Rich Ba$tard'
dough='$$$dollars$$$'
cat <<____HERE
$Name, you can win a lot of $dough this week!
Notice that \'backticks' need escaping if you want
literal text, not 'pwd', just like in variables like
\$HOME (current value: $HOME)
____HERE
Демо: https://ideone.com/rMF2XA
Обратите внимание, что любой из механизмов цитирования - \____HERE
или "____HERE"
\____HERE
или "____HERE"
\____HERE
'____HERE'
- отключит интерполяцию всех переменных и превратит '____HERE'
документ в фрагмент буквального текста.