如何将变量的值传递给命令的stdin?

91 security bash stdin

我正在编写一个应该有点安全的shell脚本,即不通过命令参数传递安全数据,最好不使用临时文件.如何将变量传递给命令的stdin?或者,如果不可能,如何正确使用临时文件进行此类任务?

Mar*_*tin 166

在stdin上传递值非常简单:

your-command <<< "$your_variable"
Run Code Online (Sandbox Code Playgroud)

始终确保在变量表达式周围加上引号!

  • 根据我所知,Herestrings` <<<`不保证可用,它们不在POSIX基础上.他们将按预期工作,只要你只在`bash`中运行它们.我只提到它,因为他们OP说'shell'不是特别'bash'.虽然他确实用'bash`标记了这个问题......所以这显然是一个可接受的答案. (37认同)
  • @StevenLu`printf'%s \n'"$ var"`产生与`echo"$ var"`相同的结果但是如果例如`var = -en`则不会破坏,甚至不需要bash . (3认同)
  • 另请注意,对于此处的字符串,换行符会附加到字符串中。 (3认同)
  • @chunk_split 如果您愿意,您可以将此处的字符串放在命令的开头: `&lt;&lt;&lt; "$your_variable" command1 | 命令2` (3认同)

Oli*_*rth 69

简单的事情:

echo "$blah" | my_cmd
Run Code Online (Sandbox Code Playgroud)

  • 让我们看看你如何处理`blah = -n`,`blah = -e` ...使用`printf`代替.http://unix.stackexchange.com/questions/65803/why-is-printf-better-than-echo (11认同)
  • 6年后,如果我可以删除这个答案,我会(但我不能,因为它已被接受......) (11认同)
  • 谨防变量中的空格:`echo"$ blah"`更好. (7认同)
  • 即使在`$ blah`中有一个```,这还能工作吗? (3认同)
  • @mallwright printenv 仅适用于导出的变量。 (3认同)

Jon*_*ler 17

请注意,' echo "$var" | command操作意味着标准输入仅限于回显的线.如果您还希望连接终端,那么您需要更高级:

{ echo "$var"; cat - ; } | command

( echo "$var"; cat -   ) | command
Run Code Online (Sandbox Code Playgroud)

这意味着第一行将是其中的内容,$var但其余部分将来自cat读取其标准输入.如果命令没有做任何太花哨的事情(尝试打开命令行编辑,或运行像是vim),那就没关系了.否则,你需要得到真正的幻想 - 我认为expect或其中一个衍生品可能是合适的.

命令行符号实际上是相同的 - 但是第二个分号对于括号是必要的,而不是括号.


Pol*_*toS 15

(cat <<END
$passwd
END
) | command
Run Code Online (Sandbox Code Playgroud)

cat不是真正需要的,但它有助于更​​好地构造代码,并允许您在括号中使用更多命令作为命令的输入.

  • 到目前为止,这是最好的答案,不会将变量内容泄漏到管道或进程监听中。 (3认同)

Kam*_*ski 15

这种健壮和便携的方式已经出现在评论中。它应该是一个独立的答案。

printf '%s' "$var" | my_cmd
Run Code Online (Sandbox Code Playgroud)

或者

printf '%s\n' "$var" | my_cmd
Run Code Online (Sandbox Code Playgroud)

笔记:

  • 它比 好echo,原因在这里:为什么printf比 好echo
  • printf "$var"是错的。第一个参数是格式,其中各种序列喜欢%s\n解释。要正确传递变量,不得将其解释为格式。
  • 通常变量不包含尾随换行符。前一个命令(with %s)按原样传递变量。然而,处理文本的工具可能会忽略或抱怨不完整的行(请参阅为什么文本文件应以换行符结尾?)。因此,您可能需要后一个命令 (with %s\n),它将换行符附加到变量的内容中。不明显的事实:

    • 这里 Bash ( <<<"$var" my_cmd) 中的string确实附加了一个换行符。
    • 任何附加换行符的方法都会导致 的非空标准输入my_cmd,即使变量为空或未定义。


Rob*_*obs 14

我喜欢Martin的答案,但根据变量中的内容,它有一些问题.这个

your-command <<< """$your_variable"""
Run Code Online (Sandbox Code Playgroud)

如果你的变量包含"或!

  • bash 解析器对 `"""foo"""` 的处理方式与 `"foo"` 完全相同。`""` 只是一个空引号对——开始和结束一个带引号的字符串,其中没有任何内容;所以你有“$your_variable”在前面和末尾与一个空的带引号的字符串连接起来。 (7认同)
  • 但为什么?另外,我无法重现任何问题:`foo1 = - ; foo2 ='"'; foo3 = \!; cat <<<"$ foo1"; cat <<<"$ foo2"; cat <<<"$ foo3"`对我来说很好.这三个究竟是什么` "做什么?AFAIK你只是在前面添加一个空字符串. (4认同)

cns*_*nst 7

根据Martin的回答,有一个名为Here Strings的bash功能(它本身是更广泛支持的Here Documents功能的变体).

http://www.gnu.org/software/bash/manual/bashref.html#Here-Strings

3.6.7这里的字符串

这里文档的一个变体,格式是:

<<< word
Run Code Online (Sandbox Code Playgroud)

该字被扩展并在其标准输入上提供给命令.

请注意,Here Strings似乎只是bash,因此,为了提高可移植性,根据PoltoS的回答,您最好使用原始的Here Documents功能:

( cat <<EOF
$variable
EOF
) | cmd
Run Code Online (Sandbox Code Playgroud)

或者,上述更简单的变体:

(cmd <<EOF
$variable
EOF
)
Run Code Online (Sandbox Code Playgroud)

您可以省略(),除非你想拥有这进一步重定向到其他命令.