简体   繁体   English

在 bash heredoc 中使用变量

[英]Using variables inside a bash heredoc

I'm trying to interpolate variables inside of a bash heredoc:我正在尝试在 bash heredoc 中插入变量:

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

This isn't working as I'd expect ( $var is treated literally, not expanded).这不像我预期的那样工作( $var按字面意思处理,而不是扩展)。

I need to use sudo tee because creating the file requires sudo.我需要使用sudo tee因为创建文件需要 sudo。 Doing something like:做类似的事情:

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

Doesn't work, because >outfile opens the file in the current shell, which is not using sudo.不起作用,因为>outfile在当前 shell 中打开文件,而当前 shell 不使用 sudo。

In answer to your first question, there's no parameter substitution because you've put the delimiter in quotes - the bash manual says :在回答您的第一个问题时,没有参数替换,因为您已将分隔符放在引号中 - bash 手册说

The format of here-documents is:这里文档的格式是:

 <<[-]word here-document delimiter

No parameter expansion, command substitution, arithmetic expansion, or pathname expansion is performed on word .不会对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.如果word中的任何字符被引用,则分隔符是 word 上去除引号的结果,并且 here-document 中的行不展开。 If word is unquoted, all lines of the here-document are subjected to parameter expansion, command substitution, and arithmetic expansion.如果word没有被引用,则 here-document 的所有行都经过参数扩展、命令替换和算术扩展。 [...] [...]

If you change your first example to use <<EOF instead of << "EOF" you'll find that it works.如果您将第一个示例更改为使用<<EOF而不是<< "EOF"您会发现它有效。

In your second example, the shell invokes sudo only with the parameter cat , and the redirection applies to the output of sudo cat as the original user.在您的第二个示例中,shell 仅使用参数cat调用sudo ,并且重定向适用于sudo cat作为原始用户的输出。 It'll work if you try:如果您尝试,它将起作用:

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

Don't use quotes with <<EOF :不要在<<EOF中使用引号:

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

Variable expansion is the default behavior inside of here-docs.变量扩展是 here-docs 内部的默认行为。 You disable that behavior by quoting the label (with single or double quotes).您可以通过引用标签(使用单引号或双引号)来禁用该行为。

As a late corolloary to the earlier answers here, you probably end up in situations where you want some but not all variables to be interpolated.作为此处较早答案的较晚推论,您可能最终会遇到希望对一些但不是所有变量进行插值的情况。 You can solve that by using backslashes to escape dollar signs and backticks;您可以通过使用反斜杠来转义美元符号和反引号来解决这个问题; or you can put the static text in a variable.或者您可以将静态文本放入变量中。

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

Demo: https://ideone.com/rMF2XA演示: https ://ideone.com/rMF2XA

Note that any of the quoting mechanisms -- \____HERE or "____HERE" or '____HERE' -- will disable all variable interpolation, and turn the here-document into a piece of literal text.请注意,任何引用机制 - \____HERE"____HERE"'____HERE' - 将禁用所有变量插值,并将 here-document 转换为一段文字文本。

A common task is to combine local variables with script which should be evaluated by a different shell, programming language, or remote host.一个常见的任务是将局部变量与脚本结合起来,脚本应该由不同的 shell、编程语言或远程主机进行评估。

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"
:

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM