在bash heredoc中使用变量


192

我正在尝试在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。


9
这是可以理解的混乱!如下所述,引用定界符的任何部分都会关闭heredoc中的扩展(就好像在中''),而不是引用定界符会开启扩展(就好像在中"")。但是,您的直觉在Perl中是正确的,其中带有单引号标识符的heredoc的行为就好像是用单引号引起来,一个带有双引号标识符的好像是用双引号引起来,而一个带有反引号的标识符就像在反引号中一样。 !见:佩洛普:<< EOF
Nils von Barth

Answers:


252

在回答第一个问题时,没有参数替换,因为您已将定界符置于引号中-bash手册中说

此处文档的格式为:

      <<[-]word
              here-document
      delimiter

没有对word执行参数扩展,命令替换,算术扩展或路径名扩展。如果单词中的任何字符都用引号引起来,则 定界符是删除单词上的引号的结果,并且本文档中的行不会扩展。如果未引用word,则此文档的所有行都将进行参数扩展,命令替换和算术扩展。[...]

如果您将第一个示例更改为<<EOF而不是,<< "EOF"则会发现它是可行的。

在第二个示例中,外壳程序sudo仅使用参数调用cat,并且重定向应用于sudo cat原始用户的输出。如果您尝试以下操作,它将起作用:

sudo sh -c "cat > /path/to/outfile" <<EOT
my text...
EOT

如果您有兴趣,也可以这样做: (cat > /path/to/outfile) <<EOFsudo sh -c ... <<EOF
Voltaire

请告诉我在Bash中埋葬是这样做的一个很好的理由。
Landon Kuhn

96

不要在引号中使用<<EOF

var=$1
sudo tee "/path/to/outfile" > /dev/null <<EOF
Some text that contains my $var
EOF

变量扩展是here-docs内部的默认行为。您可以通过引用标签(使用单引号或双引号)来禁用该行为。


36

作为此处较早答案的较晚推论,您可能最终会遇到想要插值一些但并非全部变量的情况。您可以通过使用反斜杠来避免美元符号和反引号来解决此问题;或者您可以将静态文本放入变量中。

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')都将禁用所有变量插值,并将此处文档转换为一段文字文本。

一个常见的任务是将局部变量与脚本结合在一起,而脚本应由其他外壳程序,编程语言或远程主机进行评估。

local=$(uname)
ssh -t remote <<:
    echo "$local is the value from the host which ran the ssh command"
    # Prevent here doc from expanding locally; remote won't see backslash
    remote=\$(uname)
    # Same here
    echo "\$remote is the value from the host we ssh:ed to"
:

3
不知道为什么投票失败,但是它添加了有效的注释,但该注释尚未得到较高投票。
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.