如何将变量的值传递给命令的标准输入?

我正在编写一个 shell 脚本,它应该比较安全,也就是说,不通过命令的参数传递安全数据,最好不使用临时文件。如何将变量传递给命令的标准输入?

或者,如果不可能,我如何正确地使用临时文件执行这样的任务?

122612 次浏览

试试这个:

echo "$variable" | command

简单但容易出错: 使用 echo

像这样简单的东西就能解决问题:

echo "$blah" | my_cmd

请注意,如果 $blah包含 -n-e-E等等,这可能不会正常工作; 或者如果它包含反斜杠(在缺省情况下,echo的 bash 副本保留字面反斜杠,但是将它们视为转义序列,并用相应的字符替换它们,即使没有 -e,如果可选的 XSI 扩展被启用)。

更复杂的方法: 使用 printf

printf '%s\n' "$blah" | my_cmd

这样做没有上面列出的缺点: 所有可能的 C 字符串(不包含 NULs 的字符串)都保持不变地打印出来。

(cat <<END
$passwd
END
) | command

实际上并不需要 cat,但它有助于更好地构造代码,并允许您使用括号中的更多命令作为命令的输入。

在 Bash 中向标准输入传递一个值非常简单:

your-command <<< "$your_variable"

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

请注意,这可能只在 bash中起作用,在 sh中不起作用。

注意,‘ echo "$var" | command操作意味着标准输入仅限于回显的行。如果你也想要终端连接,那么你需要更花哨一些:

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


( echo "$var"; cat -   ) | command

这意味着第一行(s)将是 $var的内容,但其余的将来自 cat读取其标准输入。如果命令没有做什么太花哨的事情(试着打开命令行编辑,或者像 vim那样运行) ,那么就没问题。否则,你需要变得非常花哨-我认为 expect或其衍生物之一可能是合适的。

命令行符号实际上是相同的——但是第二个分号对于大括号是必需的,而对于括号则不必。

根据 马丁的回答,有一个名为 Here-Strings”rel = “ nofollow noReferrer”> Here Strings 的 Bash 特性(它本身是支持更广泛的 此处文件特性的一个变体) :

3.6.7这里字符串

本文档的一个变体格式如下:

<<< word

该单词在其标准上展开并提供给命令 输入。

请注意,Here String 似乎是仅 Bash 的,因此,为了提高可移植性,您可能最好使用原始的 Here Document 特性,如 PoltoS 的回答所示:

( cat <<EOF
$variable
EOF
) | cmd

或者,上面提到的一个更简单的变体:

(cmd <<EOF
$variable
EOF
)

您可以省略 (),除非您希望将它们进一步重定向到其他命令。

我喜欢 马丁的回答,但它有一些问题取决于什么是在变量

your-command <<< """$your_variable"""

如果你的变量包含 "或者 !就更好了。

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

printf '%s' "$var" | my_cmd

或者

printf '%s\n' "$var" | my_cmd

Notes:

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

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

如果你来自一个复制品,你可能是一个初学者谁尝试做一些像

"$variable" >file

或者

"$variable" | wc -l

你明显是想说什么

echo "$variable" >file
echo "$variable" | wc -l

(真正的初学者也会忘记引号; 除非你有特定的理由去省略它们,至少在你理解引号之前。)