2011-02-08 29 views
132

我试图插一个bash定界符的内部变量:使用变量

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在当前shell中打开文件,该文件不使用sudo。

+5

这是一个可以理解的混乱!如下所述,引用分隔符的任何部分都会关闭heredoc中的扩展(就像在''''中那样),但* not *引用分隔符会使扩展开启(就像它在'“”'中一样)。 *然而,*您的直觉在Perl中是正确的,其中具有单引号标识符的heredoc表现得像在单引号中一样,其中一个带有双引号标识符就像在双引号中一样,另一个带有带勾号标识符如果在反引号!参见: [perlop:<< EOF](http://perldoc.perl.org/perlop.html#%3c%3cEOF) –

回答

177

在回答你的第一个问题,有没有参数替代,因为你已经把分隔符引号 - the bash manual says

这里,文件的格式为:

 <<[-]word 
       here-document 
     delimiter 

无参数扩展,命令替换,算术扩展或 路径名扩展在上执行。如果单词中的任何字符均为 引用,则分隔符是对单词的引用删除的结果,并且此文档中的 行不会展开。如果单词未加引号,则此文档中的所有 行均经过参数扩展,命令替换和算术扩展。 [...]

如果更改使用<<EOF,而不是<< "EOF",你会发现,它的作品你的第一个例子。

在第二个示例中,shell仅使用参数cat调用sudo,并且重定向适用于原始用户的输出sudo cat

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

扩展适用于HEREDOC中的单引号变量。 – peter2108

+0

如果你感兴趣,你也可以这样做: '(cat>/path/to/outfile)<< EOF'代替'sudo sh -c ... << EOF' – Voltaire

+0

请告诉我burash在Bash这就是为什么这样的好理由。 –

70

不要<<EOF使用引号:

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

变扩建是在这里,文档内的默认行为,如果你尝试它会工作。您通过引用标签(使用单引号或双引号)来禁用该行为。