从heredoc脚本中的stdin脚本读取并通过管道传输到“sh”

从heredoc脚本中的stdin脚本读取并通过管道传输到“sh”

这按预期工作

$> cat ./readfromstdin.sh
echo reading
cat /dev/stdin

$> echo hello | ./readfromstdin.sh
reading
hello

我正在尝试在没有临时文件的情况下实现类似的目标。我的第一次尝试是

echo hello | (echo cat /dev/stdin|sh)

这不起作用。使用heredoc它也不起作用(尽管我不确定正确的语法是什么:

echo hello | (cat << EOF | sh
cat /dev/stdin
EOF)
pipe cmdsubst pipe heredoc>

是否可以使用通过管道传输到 shell 的脚本从 stdin 读取数据?

答案1

您可以通过管道到子 shell 来相对轻松地完成您所描述的操作:

$ echo hello | ( echo reading; cat /dev/stdin )
reading
hello

我承认我真的无法想象这个的任何用例。为什么不直接做:

$ echo hello | ( echo reading; read var; echo "$var")
reading
hello

这样您就可以将标准输入内容保存为变量,并可以在闲暇时操作它们。

答案2

$ echo 'world' |  { echo 'hello'; cat }
hello
world

无需显式给出,/dev/stdin因为cat如果cat没有给出其他操作数,则默认情况下会进行操作。

在您自己的代码中,看起来好像您想传递一个命令而不是要输出的字符串。sh无论如何,这就是我解释代码中的存在的方式。但我不完全确定你需要这个。

您这样做时遇到的问题是由于将脚本提供给sh其标准输入造成的。因此,标准输入将保留用于命令,因此通过管道将字符串输入其中将不起作用。

答案3

您的意思是您想从子 shell 访问 stdin,该子 shell 已经通过 stdin 传递了命令,该命令引用了从父进程传递的 stdin ?

这真是拗口——你的意思是这样的吗:

$ cat ~/.tmp/test.sh 
#!/bin/bash
set -eu

echo i am stdin from pipe | {
    echo '0</dev/fd/100 cat -' | sh -x

} 100<&0
$ ~/.tmp/test.sh 
+ cat -
i am stdin from pipe
  • echo i am stdin from pipe重定向到fd100<&0以免丢失引用
  • '0</dev/fd/100 cat -'作为字符串传递到标准输入,并对其sh -x进行评估和执行
  • 标准输入/dev/fd/100引用被重定向/dev/stdin到进程cat -,该进程将字符串写入标准输出i am stdin from pipe

需要明确的是,永远不要这样做^^。

相关内容