在bash heredoc中使用变量

Using variables inside a bash heredoc

我正在尝试在bash heredoc中插入变量:

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

这并不像我预期的那样有效($var按字面意思处理,而不是扩展)。

我需要使用sudo tee,因为创建文件需要sudo。做一些类似的事情:

1
2
3
sudo cat > /path/to/outfile <<EOT
my text...
EOT

不起作用,因为>outfile在当前shell中打开文件,而该shell不使用sudo。


在回答第一个问题时,没有参数替换,因为您已经将分隔符用引号括起来了-bash手册说:

The format of here-documents is:

1
2
3
      <<[-]word
              here-document
      delimiter

No parameter expansion, command substitution, arithmetic expansion, or
pathname expansion is performed on word. If any characters in word are
quoted, the delimiter is the result of quote removal on word, and the
lines in the here-document are not expanded. If word is unquoted, all
lines of the here-document are subjected to parameter expansion, command substitution, and arithmetic expansion. [...]

如果您将第一个示例改为使用<而不是<<"EOF",您会发现它是有效的。

在第二个示例中,shell仅使用参数cat调用sudo,重定向应用于作为原始用户的sudo cat的输出。如果你尝试一下,它会起作用的:

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


不要在<中使用引号:

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

变量扩展是这里文档中的默认行为。您可以通过引用标签(单引号或双引号)来禁用该行为。


作为早期答案的最后一个共同点,您可能会在希望某些但不是所有变量都被插入的情况下结束。您可以通过使用反斜杠来避开美元符号和反斜杠来解决这个问题;也可以将静态文本放入变量中。

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

一个常见的任务是将局部变量与脚本结合起来,脚本应该由不同的shell、编程语言或远程主机进行评估。

1
2
3
4
5
6
7
8
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"
: