在 bash 定界文档中使用变量

发布于 2024-10-16 18:43:26 字数 421 浏览 11 评论 0 原文

我正在尝试在 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 在当前 shell 中打开文件,而当前 shell 不使用 sudo。

I'm trying to interpolate variables inside of a 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).

I need to use sudo tee because creating the file requires 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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

地狱即天堂 2024-10-23 18:43:26

在回答您的第一个问题时,没有参数替换,因为您已将分隔符放在引号中 - bash 手册说

此处文档的格式为:

<前><代码> <<[-]字
此处文档
分隔符

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

如果您将第一个示例更改为使用 < 而不是 << “EOF” 你会发现它有效。

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

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

In answer to your first question, there's no parameter substitution because you've put the delimiter in quotes - the bash manual says:

The format of here-documents is:

      <<[-]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. [...]

If you change your first example to use <<EOF instead of << "EOF" you'll find that it works.

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. It'll work if you try:

sudo sh -c "cat > /path/to/outfile" <<EOT
my text...
EOT
你爱我像她 2024-10-23 18:43:26

不要在 < 中使用引号:

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

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

Don't use quotes with <<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. You disable that behavior by quoting the label (with single or double quotes).

一绘本一梦想 2024-10-23 18:43:26

作为此处早期答案的最新推论,您可能最终会遇到这样的情况:您希望对一些变量进行插值,而不是对所有变量进行插值。您可以通过使用反斜杠来转义美元符号和反引号来解决这个问题;或者您可以将静态文本放入变量中。

Name='Rich Ba$tard'
dough='$$dollars$

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

请注意,任何引用机制 - \ ____HERE"____HERE"'____HERE' -- 将禁用所有变量插值,并将此处文档转换为一段文字。

一个常见的任务是将本地变量与脚本结合起来,脚本应该由不同的 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"
:
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、编程语言或远程主机进行评估。


As a late corollary 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$

Demo: 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.

A common task is to combine local variables with script which should be evaluated by a different shell, programming language, or remote host.

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

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.

A common task is to combine local variables with script which should be evaluated by a different shell, programming language, or remote host.



    
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文